## Table of Contents

- [What is Microlink](#what-is-microlink)
  - [CLI Microlink API example](#cli-microlink-api-example)
  - [cURL Microlink API example](#curl-microlink-api-example)
  - [JavaScript Microlink API example](#javascript-microlink-api-example)
  - [Python Microlink API example](#python-microlink-api-example)
  - [Ruby Microlink API example](#ruby-microlink-api-example)
  - [PHP Microlink API example](#php-microlink-api-example)
  - [Golang Microlink API example](#golang-microlink-api-example)
- [The core idea](#the-core-idea)
- [What you can do](#what-you-can-do)
- [See it in action](#see-it-in-action)
  - [CLI Microlink API example](#cli-microlink-api-example-1)
  - [cURL Microlink API example](#curl-microlink-api-example-1)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-1)
  - [Python Microlink API example](#python-microlink-api-example-1)
  - [Ruby Microlink API example](#ruby-microlink-api-example-1)
  - [PHP Microlink API example](#php-microlink-api-example-1)
  - [Golang Microlink API example](#golang-microlink-api-example-1)
  - [Take a screenshot](#take-a-screenshot)
  - [CLI Microlink API example](#cli-microlink-api-example-2)
  - [cURL Microlink API example](#curl-microlink-api-example-2)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-2)
  - [Python Microlink API example](#python-microlink-api-example-2)
  - [Ruby Microlink API example](#ruby-microlink-api-example-2)
  - [PHP Microlink API example](#php-microlink-api-example-2)
  - [Golang Microlink API example](#golang-microlink-api-example-2)
  - [Extract specific data](#extract-specific-data)
  - [CLI Microlink API example](#cli-microlink-api-example-3)
  - [cURL Microlink API example](#curl-microlink-api-example-3)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-3)
  - [Python Microlink API example](#python-microlink-api-example-3)
  - [Ruby Microlink API example](#ruby-microlink-api-example-3)
  - [PHP Microlink API example](#php-microlink-api-example-3)
  - [Golang Microlink API example](#golang-microlink-api-example-3)
  - [Generate a PDF](#generate-a-pdf)
  - [CLI Microlink API example](#cli-microlink-api-example-4)
  - [cURL Microlink API example](#curl-microlink-api-example-4)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-4)
  - [Python Microlink API example](#python-microlink-api-example-4)
  - [Ruby Microlink API example](#ruby-microlink-api-example-4)
  - [PHP Microlink API example](#php-microlink-api-example-4)
  - [Golang Microlink API example](#golang-microlink-api-example-4)
  - [Run custom code](#run-custom-code)
  - [CLI Microlink API example](#cli-microlink-api-example-5)
  - [cURL Microlink API example](#curl-microlink-api-example-5)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-5)
  - [Python Microlink API example](#python-microlink-api-example-5)
  - [Ruby Microlink API example](#ruby-microlink-api-example-5)
  - [PHP Microlink API example](#php-microlink-api-example-5)
  - [Golang Microlink API example](#golang-microlink-api-example-5)
- [When to use Microlink](#when-to-use-microlink)
  - [Automatic proxy resolution PRO](#automatic-proxy-resolution-pro)
  - [When something else is better](#when-something-else-is-better)
- [How requests work](#how-requests-work)
- [Combine workflows in one call](#combine-workflows-in-one-call)
  - [CLI Microlink API example](#cli-microlink-api-example-6)
  - [cURL Microlink API example](#curl-microlink-api-example-6)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-6)
  - [Python Microlink API example](#python-microlink-api-example-6)
  - [Ruby Microlink API example](#ruby-microlink-api-example-6)
  - [PHP Microlink API example](#php-microlink-api-example-6)
  - [Golang Microlink API example](#golang-microlink-api-example-6)
- [Embed assets directly](#embed-assets-directly)
- [Microlink as a tool for AI agents](#microlink-as-a-tool-for-ai-agents)
  - [Browse behind anti-bot shields](#browse-behind-anti-bot-shields)
  - [Save tokens with markdown](#save-tokens-with-markdown)
  - [CLI Microlink API example](#cli-microlink-api-example-7)
  - [cURL Microlink API example](#curl-microlink-api-example-7)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-7)
  - [Python Microlink API example](#python-microlink-api-example-7)
  - [Ruby Microlink API example](#ruby-microlink-api-example-7)
  - [PHP Microlink API example](#php-microlink-api-example-7)
  - [Golang Microlink API example](#golang-microlink-api-example-7)
  - [Give the model eyes](#give-the-model-eyes)
  - [CLI Microlink API example](#cli-microlink-api-example-8)
  - [cURL Microlink API example](#curl-microlink-api-example-8)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-8)
  - [Python Microlink API example](#python-microlink-api-example-8)
  - [Ruby Microlink API example](#ruby-microlink-api-example-8)
  - [PHP Microlink API example](#php-microlink-api-example-8)
  - [Golang Microlink API example](#golang-microlink-api-example-8)
  - [Extract structured data for tool use](#extract-structured-data-for-tool-use)
  - [CLI Microlink API example](#cli-microlink-api-example-9)
  - [cURL Microlink API example](#curl-microlink-api-example-9)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-9)
  - [Python Microlink API example](#python-microlink-api-example-9)
  - [Ruby Microlink API example](#ruby-microlink-api-example-9)
  - [PHP Microlink API example](#php-microlink-api-example-9)
  - [Golang Microlink API example](#golang-microlink-api-example-9)
  - [Why this matters](#why-this-matters)
- [Built-in caching](#built-in-caching)
- [Free to start, scales with you](#free-to-start-scales-with-you)
- [Client libraries](#client-libraries)
- [What's next](#whats-next)

---

[](https://microlink.io/docs/api/getting-started/overview)

[API](https://microlink.io/docs/api/getting-started/overview)

[](https://microlink.io/docs/guides)

GUIDES

[](https://microlink.io/docs/mql/getting-started/overview)

MQL

[](https://microlink.io/docs/sdk/getting-started/overview)

SDK

[](https://microlink.io/docs/cards/getting-started/overview)

CARDS

## What is Microlink

Microlink is an API that turns any URL into structured data, screenshots, PDFs, and more. You send a URL, Microlink opens it in a headless browser, and returns exactly what you asked for — metadata, images, documents, or custom-extracted fields — through a single HTTP GET request.

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://github.com/microlinkhq' URL:

### CLI Microlink API example

``` bash
microlink https://github.com/microlinkhq
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://github.com/microlinkhq"
```

### JavaScript Microlink API example

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://github.com/microlinkhq')
```

### Python Microlink API example

``` python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://github.com/microlinkhq"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

``` ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://github.com/microlinkhq"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

``` php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://github.com/microlinkhq"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

``` bash
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://github.com/microlinkhq")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://github.com/microlinkhq')
```

Every request starts with a URL. By default, Microlink returns normalized metadata for the page.

No infrastructure to manage. No browser to install. No Puppeteer cluster to scale. You get a production-ready API that handles rendering, caching, and asset delivery out of the box.

Plus automatic proxy resolution on any

PRO

plan to bypass IP blocking, CAPTCHAs, cookie banners, and other scraping shields, so you can reliably reach sites that actively resist automation.

## The core idea

Most web automation tasks — taking screenshots, extracting data, generating PDFs, detecting technologies — require the same underlying work: open a browser, load a page, wait for it to render, then do something with the result.

Microlink abstracts that entire pipeline into query parameters. Instead of writing and maintaining browser automation code, you describe *what you want* and the API handles *how to get it*.

``` bash
https://api.microlink.io?url=https://example.com&screenshot=true&pdf=true
```

That single URL opens a headless browser, renders the page, captures a screenshot, stores it on a CDN, and returns the asset metadata as JSON — all in one request.

## What you can do

Microlink is not a single-purpose tool. It is a general-purpose browser automation API with several built-in workflows:

| Workflow            | What it does                                                                  | Key parameter               |
| ------------------- | ----------------------------------------------------------------------------- | --------------------------- |
| **Metadata**        | Extract normalized title, description, image, author, date, logo from any URL | Default behavior            |
| **Screenshot**      | Capture a full-page or element-level image of any website                     | `screenshot`                |
| **PDF**             | Generate a printable document from any page                                   | `pdf`                       |
| **Data extraction** | Scrape specific fields using CSS selectors and extraction rules               | `data`                      |
| **Markdown**        | Convert page content to clean Markdown                                        | `data` + `attr: 'markdown'` |
| **Function**        | Run arbitrary JavaScript with full Puppeteer access                           | `function`                  |
| **Insights**        | Detect technologies behind a site or run Lighthouse audits                    | `insights`                  |

Every workflow shares the same endpoint, the same caching layer, the same authentication model, and the same response format. Learn one, and the rest follow the same pattern.

## See it in action

The default response gives you everything needed for a link preview — title, description, image, logo, author, date, language, and publisher:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://vercel.com' URL:

### CLI Microlink API example

``` bash
microlink https://vercel.com
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://vercel.com"
```

### JavaScript Microlink API example

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://vercel.com')
```

### Python Microlink API example

``` python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://vercel.com"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

``` ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://vercel.com"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

``` php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://vercel.com"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

``` bash
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://vercel.com")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://vercel.com')
```

Normalized metadata works across millions of sites without any configuration. Useful for link previews, content aggregators, and SEO tools.

### Take a screenshot

Add `screenshot: true` to capture a visual snapshot of the page:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://github.com/microlinkhq' URL with 'screenshot' & 'meta' API parameters:

### CLI Microlink API example

``` bash
microlink https://github.com/microlinkhq&screenshot
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://github.com/microlinkhq" \
  -d "screenshot=true" \
  -d "meta=false"
```

### JavaScript Microlink API example

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://github.com/microlinkhq', {
  screenshot: true,
  meta: false
})
```

### Python Microlink API example

``` python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://github.com/microlinkhq",
    "screenshot": "true",
    "meta": "false"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

``` ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://github.com/microlinkhq",
  screenshot: "true",
  meta: "false"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

``` php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://github.com/microlinkhq",
    "screenshot" => "true",
    "meta" => "false"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

``` bash
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://github.com/microlinkhq")
    q.Set("screenshot", "true")
    q.Set("meta", "false")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://github.com/microlinkhq', {

  screenshot: true,

  meta: false

})
```

The generated image is returned under `data.screenshot.url`, hosted on a CDN and ready to use.

### Extract specific data

Use `data` rules to pull exactly the fields you need from any page:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://news.ycombinator.com' URL with 'data' API parameter:

### CLI Microlink API example

``` bash
microlink https://news.ycombinator.com&data.stories.selectorAll=.athing&data.stories.attr.title.selector='.titleline > a'&data.stories.attr.title.attr=text&data.stories.attr.href.selector='.titleline > a'&data.stories.attr.href.attr=href
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://news.ycombinator.com" \
  -d "data.stories.selectorAll=.athing" \
  -d "data.stories.attr.title.selector=.titleline%20%3E%20a" \
  -d "data.stories.attr.title.attr=text" \
  -d "data.stories.attr.href.selector=.titleline%20%3E%20a" \
  -d "data.stories.attr.href.attr=href"
```

### JavaScript Microlink API example

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://news.ycombinator.com', {
  data: {
    stories: {
      selectorAll: ".athing",
      attr: {
        title: {
          selector: ".titleline > a",
          attr: "text"
        },
        href: {
          selector: ".titleline > a",
          attr: "href"
        }
      }
    }
  }
})
```

### Python Microlink API example

``` python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://news.ycombinator.com",
    "data.stories.selectorAll": ".athing",
    "data.stories.attr.title.selector": ".titleline > a",
    "data.stories.attr.title.attr": "text",
    "data.stories.attr.href.selector": ".titleline > a",
    "data.stories.attr.href.attr": "href"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

``` ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://news.ycombinator.com",
  data.stories.selectorAll: ".athing",
  data.stories.attr.title.selector: ".titleline > a",
  data.stories.attr.title.attr: "text",
  data.stories.attr.href.selector: ".titleline > a",
  data.stories.attr.href.attr: "href"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

``` php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://news.ycombinator.com",
    "data.stories.selectorAll" => ".athing",
    "data.stories.attr.title.selector" => ".titleline > a",
    "data.stories.attr.title.attr" => "text",
    "data.stories.attr.href.selector" => ".titleline > a",
    "data.stories.attr.href.attr" => "href"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

``` bash
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://news.ycombinator.com")
    q.Set("data.stories.selectorAll", ".athing")
    q.Set("data.stories.attr.title.selector", ".titleline > a")
    q.Set("data.stories.attr.title.attr", "text")
    q.Set("data.stories.attr.href.selector", ".titleline > a")
    q.Set("data.stories.attr.href.attr", "href")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://news.ycombinator.com', {

  data: {

    stories: {

      selectorAll: ".athing",

      attr: {

        title: {

          selector: ".titleline > a",

          attr: "text"

        },

        href: {

          selector: ".titleline > a",

          attr: "href"

        }

      }

    }

  }

})
```

Define what you want with CSS selectors. Microlink renders the page in a real browser first, so JavaScript-heavy sites work too.

### Generate a PDF

Turn any page into a printable document:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://example.com' URL with 'pdf' & 'meta' API parameters:

### CLI Microlink API example

``` bash
microlink https://example.com&pdf
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://example.com" \
  -d "pdf=true" \
  -d "meta=false"
```

### JavaScript Microlink API example

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://example.com', {
  pdf: true,
  meta: false
})
```

### Python Microlink API example

``` python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://example.com",
    "pdf": "true",
    "meta": "false"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

``` ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://example.com",
  pdf: "true",
  meta: "false"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

``` php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://example.com",
    "pdf" => "true",
    "meta" => "false"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

``` bash
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://example.com")
    q.Set("pdf", "true")
    q.Set("meta", "false")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://example.com', {

  pdf: true,

  meta: false

})
```

The PDF is generated from a real browser render, so the output matches what you see in the browser print dialog.

### Run custom code

When built-in parameters are not enough, run your own JavaScript inside the headless browser:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://news.ycombinator.com' URL with 'function' & 'meta' API parameters:

### CLI Microlink API example

``` bash
microlink https://news.ycombinator.com&function='({ page }) => page.evaluate(() => `There are ${document.querySelectorAll("a[href]").length} links`)'
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://news.ycombinator.com" \
  -d "function=(%7B%20page%20%7D)%20%3D%3E%20page.evaluate(()%20%3D%3E%20%60There%20are%20%24%7Bdocument.querySelectorAll(%22a%5Bhref%5D%22).length%7D%20links%60)" \
  -d "meta=false"
```

### JavaScript Microlink API example

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://news.ycombinator.com', {
  function: '({ page }) => page.evaluate(() => `There are ${document.querySelectorAll("a[href]").length} links`)',
  meta: false
})
```

### Python Microlink API example

``` python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://news.ycombinator.com",
    "function": '''({ page }) => page.evaluate(() => `There are ${document.querySelectorAll("a[href]").length} links`)''',
    "meta": "false"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

``` ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://news.ycombinator.com",
  function: '({ page }) => page.evaluate(() => `There are ${document.querySelectorAll("a[href]").length} links`)',
  meta: "false"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

``` php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://news.ycombinator.com",
    "function" => '({ page }) => page.evaluate(() => `There are ${document.querySelectorAll("a[href]").length} links`)',
    "meta" => "false"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

``` bash
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    fn := `({ page }) => page.evaluate(() => `There are ${document.querySelectorAll("a[href]").length} links`)`

    q := u.Query()
    q.Set("url", "https://news.ycombinator.com")
    q.Set("function", fn)
    q.Set("meta", "false")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://news.ycombinator.com', {

  function: '({ page }) => page.evaluate(() => `There are ${document.querySelectorAll("a[href]").length} links`)',

  meta: false

})
```

Full Puppeteer access through a single API call. No infrastructure to manage.

## When to use Microlink

Microlink is the right tool when you need browser rendering without owning browser infrastructure:

- **Link previews** — show a rich card (title, image, description) for any URL your users share.
- **Social cards and OG images** — generate dynamic `og:image` screenshots for blog posts, profiles, or dashboards.
- **Web scraping** — extract structured data from pages that require JavaScript rendering.
- **PDF generation** — convert invoices, reports, or articles into downloadable documents.
- **Content pipelines** — convert web pages to Markdown for CMS imports or LLM training data.
- **Competitive intelligence** — detect the tech stack behind any website.
- **Performance monitoring** — run Lighthouse audits programmatically without a local Chrome installation.
- **Automated testing** — capture visual snapshots for regression testing across devices and viewports.
- **Hard-to-reach sites** — scrape or screenshot pages protected by CAPTCHAs, IP blocking, cookie banners, or bot detection.
- **AI agents and LLMs** — give your agent eyes and hands on the web: browse behind proxy shields, convert pages to Markdown to save tokens, and take screenshots so the model can see what's on screen.

### Automatic proxy resolution PRO

Many websites actively block automated requests through IP rate limiting, CAPTCHAs, anti-bot shields, or geo-restrictions. With a

PRO

plan, Microlink includes **automatic proxy resolution** — the API routes requests through rotating, high-quality proxies so you don't have to deal with blocking yourself.

This means you can reliably extract data, take screenshots, or generate PDFs from sites that resist scraping, without configuring or paying for a separate proxy service. The proxy infrastructure is .

You can also bring your own proxy if you need a specific geographic location or a provider you already pay for. See the [proxy reference](https://microlink.io/docs/api/parameters/proxy) for details.

### When something else is better

Microlink is not the best fit for every scenario:

| Scenario                                                                        | Better alternative                        |
| ------------------------------------------------------------------------------- | ----------------------------------------- |
| You need to crawl thousands of pages following links                            | A dedicated crawler (Scrapy, Crawlee)     |
| You need real-time, bidirectional browser interaction (debugging, live preview) | A local Puppeteer or Playwright instance  |
| You only need static HTML — no JavaScript rendering required                    | A simple HTTP client (`fetch`, `curl`)    |
| You need to store large volumes of scraped data                                 | A scraping platform with built-in storage |

## How requests work

Every Microlink request follows the same lifecycle:

1.  **You send a URL** plus optional parameters via HTTP GET.
2.  **Microlink opens the page** in a headless browser (Chromium), handling JavaScript, redirects, and rendering.
3.  **The API executes your request** — metadata extraction, screenshot capture, data rules, functions, or any combination.
4.  **Assets are stored on a CDN** and cached according to the TTL you configure.
5.  **You get a JSON response** with the results, or a direct asset response if you use `embed`.

The response always includes a `status` field (`success` or `fail`) and a `data` object with the requested fields:

``` json
{

  "status": "success",

  "data": {

    "title": "microlink.io",

    "description": "Turn websites into data.",

    "image": {

      "url": "https://avatars0.githubusercontent.com/u/29799436?s=280&v=4",

      "type": "png",

      "size": 4118,

      "width": 280,

      "height": 280,

      "size_pretty": "4.12 kB"

    }

  }

}
```

## Combine workflows in one call

A single request can produce multiple outputs. For example, extract metadata *and* take a screenshot at the same time:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://github.com/microlinkhq' URL with 'screenshot' API parameter:

### CLI Microlink API example

``` bash
microlink https://github.com/microlinkhq&screenshot
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://github.com/microlinkhq" \
  -d "screenshot=true"
```

### JavaScript Microlink API example

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://github.com/microlinkhq', {
  screenshot: true
})
```

### Python Microlink API example

``` python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://github.com/microlinkhq",
    "screenshot": "true"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

``` ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://github.com/microlinkhq",
  screenshot: "true"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

``` php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://github.com/microlinkhq",
    "screenshot" => "true"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

``` bash
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://github.com/microlinkhq")
    q.Set("screenshot", "true")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://github.com/microlinkhq', {

  screenshot: true

})
```

The response includes both `data.screenshot` and the normalized metadata fields. Disable metadata with `meta: false` when you only need the screenshot.

## Embed assets directly

Instead of parsing JSON, you can make the API URL behave like a direct image, PDF, or any other asset. Use `embed` to reference the field you want:

``` html
<img src='https://api.microlink.io/?url=https://github.com/microlinkhq&screenshot&meta=false&embed=screenshot.url' />
```

This turns the API URL into a live screenshot you can use in `<img>` tags, CSS `background-image`, Markdown, or Open Graph meta tags — no JavaScript required.

## Microlink as a tool for AI agents

LLMs and autonomous agents need to interact with the web, but they face two problems: most websites block bot traffic, and raw HTML wastes context window tokens. Microlink solves both.

### Browse behind anti-bot shields

Agents that call URLs directly get blocked by CAPTCHAs, IP rate limits, and bot-detection scripts. Because Microlink renders pages through a real browser with automatic proxy resolution on

PRO

plans, the agent can reach virtually any site without managing proxies or solving challenges itself.

### Save tokens with markdown

Feeding raw HTML to an LLM is expensive and noisy — a typical page is 80%+ markup, scripts, and styling that carries no useful information. Convert the page to clean Markdown instead and send only the content the model needs:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://example.com' URL with 'data' & 'meta' API parameters:

### CLI Microlink API example

``` bash
microlink https://example.com&data.content.selector=body&data.content.attr=markdown
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://example.com" \
  -d "data.content.selector=body" \
  -d "data.content.attr=markdown" \
  -d "meta=false"
```

### JavaScript Microlink API example

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://example.com', {
  data: {
    content: {
      selector: "body",
      attr: "markdown"
    }
  },
  meta: false
})
```

### Python Microlink API example

``` python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://example.com",
    "data.content.selector": "body",
    "data.content.attr": "markdown",
    "meta": "false"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

``` ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://example.com",
  data.content.selector: "body",
  data.content.attr: "markdown",
  meta: "false"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

``` php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://example.com",
    "data.content.selector" => "body",
    "data.content.attr" => "markdown",
    "meta" => "false"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

``` bash
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://example.com")
    q.Set("data.content.selector", "body")
    q.Set("data.content.attr", "markdown")
    q.Set("meta", "false")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://example.com', {

  data: {

    content: {

      selector: "body",

      attr: "markdown"

    }

  },

  meta: false

})
```

The Markdown output strips navigation, ads, and boilerplate. A page that would cost thousands of tokens as HTML fits in a fraction of that as Markdown.

### Give the model eyes

Some tasks require the agent to *see* a page — verifying a layout, reading a chart, or understanding a visual element that isn't represented in the DOM. A screenshot gives the model a visual snapshot it can reason about:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://github.com/microlinkhq' URL with 'screenshot' & 'meta' API parameters:

### CLI Microlink API example

``` bash
microlink https://github.com/microlinkhq&screenshot
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://github.com/microlinkhq" \
  -d "screenshot=true" \
  -d "meta=false"
```

### JavaScript Microlink API example

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://github.com/microlinkhq', {
  screenshot: true,
  meta: false
})
```

### Python Microlink API example

``` python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://github.com/microlinkhq",
    "screenshot": "true",
    "meta": "false"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

``` ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://github.com/microlinkhq",
  screenshot: "true",
  meta: "false"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

``` php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://github.com/microlinkhq",
    "screenshot" => "true",
    "meta" => "false"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

``` bash
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://github.com/microlinkhq")
    q.Set("screenshot", "true")
    q.Set("meta", "false")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://github.com/microlinkhq', {

  screenshot: true,

  meta: false

})
```

Feed the screenshot URL to a vision-capable model. The agent can describe, compare, or act on what it sees.

### Extract structured data for tool use

Instead of asking the LLM to parse HTML, extract exactly the fields the agent needs as structured JSON — ready for tool calls, database writes, or downstream logic:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://news.ycombinator.com' URL with 'data' & 'meta' API parameters:

### CLI Microlink API example

``` bash
microlink https://news.ycombinator.com&data.stories.selectorAll=.athing&data.stories.attr.title.selector='.titleline > a'&data.stories.attr.title.attr=text&data.stories.attr.href.selector='.titleline > a'&data.stories.attr.href.attr=href
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://news.ycombinator.com" \
  -d "data.stories.selectorAll=.athing" \
  -d "data.stories.attr.title.selector=.titleline%20%3E%20a" \
  -d "data.stories.attr.title.attr=text" \
  -d "data.stories.attr.href.selector=.titleline%20%3E%20a" \
  -d "data.stories.attr.href.attr=href" \
  -d "meta=false"
```

### JavaScript Microlink API example

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://news.ycombinator.com', {
  data: {
    stories: {
      selectorAll: ".athing",
      attr: {
        title: {
          selector: ".titleline > a",
          attr: "text"
        },
        href: {
          selector: ".titleline > a",
          attr: "href"
        }
      }
    }
  },
  meta: false
})
```

### Python Microlink API example

``` python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://news.ycombinator.com",
    "data.stories.selectorAll": ".athing",
    "data.stories.attr.title.selector": ".titleline > a",
    "data.stories.attr.title.attr": "text",
    "data.stories.attr.href.selector": ".titleline > a",
    "data.stories.attr.href.attr": "href",
    "meta": "false"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

``` ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://news.ycombinator.com",
  data.stories.selectorAll: ".athing",
  data.stories.attr.title.selector: ".titleline > a",
  data.stories.attr.title.attr: "text",
  data.stories.attr.href.selector: ".titleline > a",
  data.stories.attr.href.attr: "href",
  meta: "false"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

``` php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://news.ycombinator.com",
    "data.stories.selectorAll" => ".athing",
    "data.stories.attr.title.selector" => ".titleline > a",
    "data.stories.attr.title.attr" => "text",
    "data.stories.attr.href.selector" => ".titleline > a",
    "data.stories.attr.href.attr" => "href",
    "meta" => "false"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

``` bash
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://news.ycombinator.com")
    q.Set("data.stories.selectorAll", ".athing")
    q.Set("data.stories.attr.title.selector", ".titleline > a")
    q.Set("data.stories.attr.title.attr", "text")
    q.Set("data.stories.attr.href.selector", ".titleline > a")
    q.Set("data.stories.attr.href.attr", "href")
    q.Set("meta", "false")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

``` javascript
import mql from '@microlink/mql'

const { data } = await mql('https://news.ycombinator.com', {

  data: {

    stories: {

      selectorAll: ".athing",

      attr: {

        title: {

          selector: ".titleline > a",

          attr: "text"

        },

        href: {

          selector: ".titleline > a",

          attr: "href"

        }

      }

    }

  },

  meta: false

})
```

The agent gets clean JSON it can use directly — no parsing, no hallucinated selectors, no wasted tokens.

### Why this matters

| Without Microlink                                  | With Microlink                                       |
| -------------------------------------------------- | ---------------------------------------------------- |
| Agent fetches HTML, gets blocked by CAPTCHA        | Automatic proxy resolution bypasses anti-bot shields |
| Raw HTML eats 10,000+ tokens per page              | Markdown conversion cuts token usage by 80%+         |
| Agent cannot see visual content                    | Screenshot gives the model a visual snapshot         |
| LLM parses messy HTML, hallucinates structure      | Structured JSON extraction returns exact fields      |
| You manage headless browsers, proxies, and retries | One HTTP GET call, zero infrastructure               |

## Built-in caching

Every response is cached on a global CDN. You control freshness with two parameters:

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr>
<th>Parameter</th>
<th>What it does</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>ttl</code>
<p>PRO</p></td>
<td>How long the cached response is considered fresh</td>
<td>24 hours</td>
</tr>
<tr>
<td><code>staleTtl</code>
<p>PRO</p></td>
<td>How long a stale response can be served while Microlink refreshes it in the background</td>
<td>0</td>
</tr>
<tr>
<td><code>force</code>
<p>PRO</p></td>
<td>Bypass the cache entirely and generate a fresh response</td>
<td><code>false</code></td>
</tr>
</tbody>
</table>

For most production use cases, the best setup is `ttl: '1d'` with `staleTtl: 0` — the user always gets an instant response, and Microlink refreshes the cache in the background.

See [caching patterns](https://microlink.io/docs/guides/common/caching) for the full strategy.

## Free to start, scales with you

The API works **without an API key**. You get **50 free requests per day**, which is enough to build and test your integration. No signup, no credit card.

When you are ready for production, a

PRO

plan unlocks higher quotas, configurable cache TTL, custom headers, proxy support, and priority rendering. See [rate limit](https://microlink.io/docs/api/basics/rate-limit) and [authentication](https://microlink.io/docs/api/basics/authentication) for details.

## Client libraries

You can call the API from any language that supports HTTP GET, but Microlink provides official libraries for a smoother developer experience:

| Library                                                       | Use case                                                                  |
| ------------------------------------------------------------- | ------------------------------------------------------------------------- |
| [MQL](https://microlink.io/docs/mql/getting-started/overview) | JavaScript/TypeScript client for Node.js, Edge runtimes, and the browser  |
| [SDK](https://microlink.io/docs/sdk/getting-started/overview) | Drop-in React, Vue, and vanilla JS components for rendering link previews |
| [CLI](https://microlink.io/docs/api/getting-started/cli)      | Explore the API from your terminal during local development               |

## What's next

Now that you understand what Microlink does, pick the workflow that matches your goal:

- **[Screenshot](https://microlink.io/docs/guides/screenshot)** — capture high-quality images of any website.
- **[Data extraction](https://microlink.io/docs/guides/data-extraction)** — scrape structured data with CSS selectors.
- **[Metadata](https://microlink.io/docs/guides/metadata)** — get normalized link preview data.
- **[PDF](https://microlink.io/docs/guides/pdf)** — generate printable documents from any page.
- **[Markdown](https://microlink.io/docs/guides/markdown)** — convert pages to clean Markdown.
- **[Function](https://microlink.io/docs/guides/function)** — run JavaScript with full Puppeteer access.
- **[Insights](https://microlink.io/docs/guides/insights)** — detect technologies or run Lighthouse audits.

Or jump to [production patterns](https://microlink.io/docs/guides/common/production-patterns) if you are ready to integrate.