## Table of Contents

- [Page preparation](#page-preparation)
- [Choose fetch mode first](#choose-fetch-mode-first)
  - [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)
- [Wait for dynamic pages to settle](#wait-for-dynamic-pages-to-settle)
  - [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)
- [Disable JavaScript when it is not helping](#disable-javascript-when-it-is-not-helping)
  - [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)
- [Use fixed waits sparingly](#use-fixed-waits-sparingly)
  - [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)

---

[](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

## Page preparation

Metadata extraction is only as good as the page Microlink sees. On static sites, the default behavior is usually enough. On dynamic or hydration-heavy sites, you may need to control how the page is fetched and when extraction happens.

## Choose fetch mode first

The biggest rendering decision is `prerender`:

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

### CLI Microlink API example

``` bash
microlink https://vercel.com&meta.title&meta.description
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://vercel.com" \
  -d "meta.title=true" \
  -d "meta.description=true" \
  -d "prerender=false"
```

### JavaScript Microlink API example

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

const { data } = await mql('https://vercel.com', {
  meta: {
    title: true,
    description: true
  },
  prerender: false
})
```

### Python Microlink API example

``` python
import requests

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

querystring = {
    "url": "https://vercel.com",
    "meta.title": "true",
    "meta.description": "true",
    "prerender": "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://vercel.com",
  meta.title: "true",
  meta.description: "true",
  prerender: "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://vercel.com",
    "meta.title" => "true",
    "meta.description" => "true",
    "prerender" => "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://vercel.com")
    q.Set("meta.title", "true")
    q.Set("meta.description", "true")
    q.Set("prerender", "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://vercel.com', {

  meta: {

    title: true,

    description: true

  },

  prerender: false

})
```

Use `prerender: false` when the metadata is already present in the initial HTML and you do not need a browser render.

| If the page                                                            | Use                           |
| ---------------------------------------------------------------------- | ----------------------------- |
| Is static HTML or simple server-rendered markup                        | `prerender: false`            |
| Might need a browser, but you are not sure                             | `prerender: 'auto'` (default) |
| Is client-rendered and comes back incomplete without browser execution | `prerender: true`             |

`prerender` is often the difference between getting real metadata and getting a generic shell.

## Wait for dynamic pages to settle

If the page needs browser rendering, you can control when Microlink considers it ready:

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

### CLI Microlink API example

``` bash
microlink https://dev.to&meta.title&meta.description&waitUntil=domcontentloaded&waitForSelector=main
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://dev.to" \
  -d "meta.title=true" \
  -d "meta.description=true" \
  -d "waitUntil=domcontentloaded" \
  -d "waitForSelector=main"
```

### JavaScript Microlink API example

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

const { data } = await mql('https://dev.to', {
  meta: {
    title: true,
    description: true
  },
  waitUntil: "domcontentloaded",
  waitForSelector: "main"
})
```

### Python Microlink API example

``` python
import requests

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

querystring = {
    "url": "https://dev.to",
    "meta.title": "true",
    "meta.description": "true",
    "waitUntil": "domcontentloaded",
    "waitForSelector": "main"
}

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://dev.to",
  meta.title: "true",
  meta.description: "true",
  waitUntil: "domcontentloaded",
  waitForSelector: "main"
}

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://dev.to",
    "meta.title" => "true",
    "meta.description" => "true",
    "waitUntil" => "domcontentloaded",
    "waitForSelector" => "main"
];

$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://dev.to")
    q.Set("meta.title", "true")
    q.Set("meta.description", "true")
    q.Set("waitUntil", "domcontentloaded")
    q.Set("waitForSelector", "main")
    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://dev.to', {

  meta: {

    title: true,

    description: true

  },

  waitUntil: "domcontentloaded",

  waitForSelector: "main"

})
```

Start with a fast lifecycle event, then wait for a stable selector that signals the page is really ready.

Use the wait controls in this order:

| Need                                       | Best option                     |
| ------------------------------------------ | ------------------------------- |
| A good default navigation signal           | `waitUntil: 'auto'`             |
| Faster navigation before a selector wait   | `waitUntil: 'domcontentloaded'` |
| A stable signal that the page has rendered | `waitForSelector`               |
| A last-resort fixed wait                   | `waitForTimeout`                |

You can also pass an array to `waitUntil` when one event alone is not enough.

## Disable JavaScript when it is not helping

If the site already exposes the metadata you need in the HTML, JavaScript can be unnecessary:

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 'meta' & 'javascript' API parameters:

### CLI Microlink API example

``` bash
microlink https://news.ycombinator.com&meta.title&meta.description
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://news.ycombinator.com" \
  -d "meta.title=true" \
  -d "meta.description=true" \
  -d "javascript=false"
```

### JavaScript Microlink API example

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

const { data } = await mql('https://news.ycombinator.com', {
  meta: {
    title: true,
    description: true
  },
  javascript: false
})
```

### Python Microlink API example

``` python
import requests

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

querystring = {
    "url": "https://news.ycombinator.com",
    "meta.title": "true",
    "meta.description": "true",
    "javascript": "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",
  meta.title: "true",
  meta.description: "true",
  javascript: "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",
    "meta.title" => "true",
    "meta.description" => "true",
    "javascript" => "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("meta.title", "true")
    q.Set("meta.description", "true")
    q.Set("javascript", "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', {

  meta: {

    title: true,

    description: true

  },

  javascript: false

})
```

Disabling JavaScript can reduce rendering work when the target site already exposes the right metadata in the initial document.

This is most useful for static sites, classic server-rendered pages, and pages where JavaScript adds noise rather than value.

## Use fixed waits sparingly

If there is no stable selector to wait for, use `waitForTimeout` as a last resort:

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

### CLI Microlink API example

``` bash
microlink https://dev.to&meta.title&meta.description&waitForTimeout=3s
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://dev.to" \
  -d "meta.title=true" \
  -d "meta.description=true" \
  -d "waitForTimeout=3s"
```

### JavaScript Microlink API example

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

const { data } = await mql('https://dev.to', {
  meta: {
    title: true,
    description: true
  },
  waitForTimeout: "3s"
})
```

### Python Microlink API example

``` python
import requests

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

querystring = {
    "url": "https://dev.to",
    "meta.title": "true",
    "meta.description": "true",
    "waitForTimeout": "3s"
}

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://dev.to",
  meta.title: "true",
  meta.description: "true",
  waitForTimeout: "3s"
}

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://dev.to",
    "meta.title" => "true",
    "meta.description" => "true",
    "waitForTimeout" => "3s"
];

$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://dev.to")
    q.Set("meta.title", "true")
    q.Set("meta.description", "true")
    q.Set("waitForTimeout", "3s")
    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://dev.to', {

  meta: {

    title: true,

    description: true

  },

  waitForTimeout: "3s"

})
```

Fixed waits work, but selector-based waits are usually faster and more reliable.

If you still cannot get the right result, continue with [troubleshooting](https://microlink.io/docs/guides/metadata/troubleshooting).

Learn how to keep metadata requests fast and fresh in [caching and performance](https://microlink.io/docs/guides/metadata/caching-and-performance).