## Table of Contents

- [Function](#function)
- [Your first function](#your-first-function)
  - [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)
- [MQL installation](#mql-installation)
- [How function execution works](#how-function-execution-works)
- [Choose the lightest tool](#choose-the-lightest-tool)
- [What your function receives](#what-your-function-receives)
- [Pass your own parameters](#pass-your-own-parameters)
  - [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)
- [Two execution contexts](#two-execution-contexts)
- [Return structured data](#return-structured-data)
  - [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)
- [When you really need page.evaluate](#when-you-really-need-pageevaluate)
- [Use npm packages](#use-npm-packages)
  - [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)
  - [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)
- [Compress large functions](#compress-large-functions)
- [Free tier, API key, and local testing](#free-tier-api-key-and-local-testing)
  - [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)
- [Common failure modes](#common-failure-modes)
- [What's next](#whats-next)
- [See also](#see-also)

---

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

## Function

The `function` parameter is Microlink's escape hatch. When `data`, `metadata`, `screenshot`, or `pdf` gets you close but not all the way, you can send JavaScript that Microlink executes remotely inside the same headless Chromium request.

You keep the no-infrastructure model: no Lambda bundle, no browser fleet, and no server to maintain. Microlink executes the code in a safe remote runtime with Puppeteer access and wraps the result under `data.function`, with the resolved value at `data.function.value`.

## Your first function

Pass a JavaScript function as a string. This example uses a public MDN page and the simplest reliable Puppeteer helper, `page.title()`:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://developer.mozilla.org/en-US/docs/Web/API/Document/title' URL with 'function' & 'meta' API parameters:

### CLI Microlink API example

``` bash
microlink https://developer.mozilla.org/en-US/docs/Web/API/Document/title&function='({ page }) => page.title()'
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://developer.mozilla.org/en-US/docs/Web/API/Document/title" \
  -d "function=(%7B%20page%20%7D)%20%3D%3E%20page.title()" \
  -d "meta=false"
```

### JavaScript Microlink API example

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

const { data } = await mql('https://developer.mozilla.org/en-US/docs/Web/API/Document/title', {
  function: "({ page }) => page.title()",
  meta: false
})
```

### Python Microlink API example

``` python
import requests

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

querystring = {
    "url": "https://developer.mozilla.org/en-US/docs/Web/API/Document/title",
    "function": "({ page }) => page.title()",
    "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://developer.mozilla.org/en-US/docs/Web/API/Document/title",
  function: "({ page }) => page.title()",
  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://developer.mozilla.org/en-US/docs/Web/API/Document/title",
    "function" => "({ page }) => page.title()",
    "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://developer.mozilla.org/en-US/docs/Web/API/Document/title")
    q.Set("function", "({ page }) => page.title()")
    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://developer.mozilla.org/en-US/docs/Web/API/Document/title', {

  function: "({ page }) => page.title()",

  meta: false

})
```

The function runs remotely after the page loads. On success, Microlink returns the result at `data.function.value`. The examples in this guide use fully public pages and `meta: false` to keep them friendly to the free plan.

The response contains the returned value:

``` json
{

  "status": "success",

  "data": {

    "function": {

      "isFulfilled": true,

      "value": "Document: title property - Web APIs | MDN"

    }

  }

}
```

## MQL installation

To run the JavaScript examples with MQL, install `@microlink/mql`:

``` bash
npm install @microlink/mql --save
```

It works in Node.js, Edge runtimes, and the browser. You can still call the API from any HTTP client, but MQL is usually the easiest option once your function needs serialization or compression.

If you prefer a higher-level wrapper, [](https://www.npmjs.com/package/@microlink/function)

`@microlink/function`

decorates a local function and sends it to the same remote runtime described in this guide. It is useful when you want to author reusable "serverless-style" helpers instead of managing `code.toString()` yourself.

## How function execution works

Every function request follows the same flow:

1.  Microlink opens the target `url` in headless Chromium.
2.  The request can also include page-preparation parameters such as `scripts`, `modules`, `click`, or `waitForSelector`.
3.  Microlink calls your function with `page`, `response`, `html`, and any extra parameters you passed in the request.
4.  Whatever your function returns or resolves to is wrapped into `data.function`, and the actual result is available at `data.function.value`.

Because `function` is just another Microlink parameter, you can also combine it with other workflows in the same request, such as `screenshot: true` or `pdf: true`, when you need custom page preparation before generating the final output.

## Choose the lightest tool

Use `function` when the built-in parameters stop being expressive enough, not as the default for every workflow.

| If you need                                                | Best option                       | Why                                                                    |
| ---------------------------------------------------------- | --------------------------------- | ---------------------------------------------------------------------- |
| Simple field extraction from the DOM                       | `data`                            | Declarative rules are shorter, easier to maintain, and easier to reuse |
| Inject CSS or JavaScript before another workflow           | `styles`, `modules`, or `scripts` | Lighter than full browser automation                                   |
| Click, wait, compute, reshape, or orchestrate custom logic | `function`                        | You get Puppeteer access plus a curated `require()` allowlist          |

For simpler extraction flows, start with [data extraction](https://microlink.io/docs/guides/data-extraction) and only escalate to `function` when the declarative approach becomes limiting.

## What your function receives

Your function is called with an object containing:

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr>
<th>Property</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>page</code></td>
<td>[](https://pptr.dev/api/puppeteer.page)
<p>Page</p></td>
<td>Full Puppeteer access for clicks, waits, evaluation, navigation, and page inspection</td>
</tr>
<tr>
<td><code>response</code></td>
<td>[](https://pptr.dev/api/puppeteer.httpresponse)
<p>HTTPResponse</p></td>
<td>The response returned by the implicit navigation</td>
</tr>
<tr>
<td><code>html</code></td>
<td><code>string</code></td>
<td>Page markup when available. If you disable metadata and still need HTML, prefer <code>page.content()</code></td>
</tr>
<tr>
<td>any extra parameter</td>
<td>depends on what you pass</td>
<td>Custom inputs such as selectors, flags, thresholds, or field names</td>
</tr>
</tbody>
</table>

That last point is important: any extra parameter you include in the request is forwarded to the function as a property on the first argument.

In practice, most first implementations should start with `page` helpers such as `page.title()`, `page.$eval()`, or `page.$$eval()`. They are easier to read and easier to debug than reaching for a large `page.evaluate(...)` block immediately.

## Pass your own parameters

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://developer.mozilla.org/en-US/docs/Web/API/Document/title' URL with 'function', 'label' & 'meta' API parameters:

### CLI Microlink API example

``` bash
microlink https://developer.mozilla.org/en-US/docs/Web/API/Document/title&function='({ page, label }) =>
  page.title().then(title => ({ label, title }))'&label='Current page title'
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://developer.mozilla.org/en-US/docs/Web/API/Document/title" \
  -d "function=(%7B%20page%2C%20label%20%7D)%20%3D%3E%0A%20%20page.title().then(title%20%3D%3E%20(%7B%20label%2C%20title%20%7D))" \
  -d "label=Current%20page%20title" \
  -d "meta=false"
```

### JavaScript Microlink API example

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

const { data } = await mql('https://developer.mozilla.org/en-US/docs/Web/API/Document/title', {
  function: "({ page, label }) =>
  page.title().then(title => ({ label, title }))",
  label: "Current page title",
  meta: false
})
```

### Python Microlink API example

``` python
import requests

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

querystring = {
    "url": "https://developer.mozilla.org/en-US/docs/Web/API/Document/title",
    "function": '''({ page, label }) =>
  page.title().then(title => ({ label, title }))''',
    "label": "Current page title",
    "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://developer.mozilla.org/en-US/docs/Web/API/Document/title",
  function: "({ page, label }) =>
  page.title().then(title => ({ label, title }))",
  label: "Current page title",
  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://developer.mozilla.org/en-US/docs/Web/API/Document/title",
    "function" => "({ page, label }) =>
  page.title().then(title => ({ label, title }))",
    "label" => "Current page title",
    "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, label }) =>
  page.title().then(title => ({ label, title }))`

    q := u.Query()
    q.Set("url", "https://developer.mozilla.org/en-US/docs/Web/API/Document/title")
    q.Set("function", fn)
    q.Set("label", "Current page title")
    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://developer.mozilla.org/en-US/docs/Web/API/Document/title', {

  function: "({ page, label }) =>

  page.title().then(title => ({ label, title }))",

  label: "Current page title",

  meta: false

})
```

The custom `label` parameter is forwarded into the function. This is the simplest way to make one function reusable across different requests.

## Two execution contexts

There are two different places your code can run, and it helps to keep them separate in your head:

| Code runs in              | Good for                                                                       | Can access                                                     |
| ------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------------------- |
| The outer `function` body | Orchestration, Puppeteer calls, `require()`, and response shaping              | `page`, `response`, forwarded params, and allowed npm packages |
| `page.evaluate(...)`      | Reading or computing values from the live DOM when page helpers are not enough | `window`, `document`, `performance`, and page state            |

A good rule of thumb: start with Puppeteer helpers such as `page.title()`, `page.$eval()`, and `page.$$eval()`. Reach for `page.evaluate(...)` only when the logic truly belongs inside the page context. Do not rely on `require()` inside `page.evaluate`.

## Return structured data

Functions can return strings, numbers, booleans, arrays, or plain objects, so they are a good fit when the result shape is unique to your application:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://developer.mozilla.org/en-US/docs/Web/API/Document/title' URL with 'function' & 'meta' API parameters:

### CLI Microlink API example

``` bash
microlink https://developer.mozilla.org/en-US/docs/Web/API/Document/title&function='({ page }) =>
  page.title().then(title => ({
    title,
    titleLength: title.length,
    words: title.split(/\s+/)
  }))'
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://developer.mozilla.org/en-US/docs/Web/API/Document/title" \
  -d "function=(%7B%20page%20%7D)%20%3D%3E%0A%20%20page.title().then(title%20%3D%3E%20(%7B%0A%20%20%20%20title%2C%0A%20%20%20%20titleLength%3A%20title.length%2C%0A%20%20%20%20words%3A%20title.split(%2F%5Cs%2B%2F)%0A%20%20%7D))" \
  -d "meta=false"
```

### JavaScript Microlink API example

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

const { data } = await mql('https://developer.mozilla.org/en-US/docs/Web/API/Document/title', {
  function: "({ page }) =>
  page.title().then(title => ({
    title,
    titleLength: title.length,
    words: title.split(/\s+/)
  }))",
  meta: false
})
```

### Python Microlink API example

``` python
import requests

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

querystring = {
    "url": "https://developer.mozilla.org/en-US/docs/Web/API/Document/title",
    "function": '''({ page }) =>
  page.title().then(title => ({
    title,
    titleLength: title.length,
    words: title.split(/\s+/)
  }))''',
    "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://developer.mozilla.org/en-US/docs/Web/API/Document/title",
  function: "({ page }) =>
  page.title().then(title => ({
    title,
    titleLength: title.length,
    words: title.split(/\s+/)
  }))",
  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://developer.mozilla.org/en-US/docs/Web/API/Document/title",
    "function" => "({ page }) =>
  page.title().then(title => ({
    title,
    titleLength: title.length,
    words: title.split(/\s+/)
  }))",
    "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.title().then(title => ({
    title,
    titleLength: title.length,
    words: title.split(/\s+/)
  }))`

    q := u.Query()
    q.Set("url", "https://developer.mozilla.org/en-US/docs/Web/API/Document/title")
    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://developer.mozilla.org/en-US/docs/Web/API/Document/title', {

  function: "({ page }) =>

  page.title().then(title => ({

    title,

    titleLength: title.length,

    words: title.split(/\s+/)

  }))",

  meta: false

})
```

Returning an object is often more useful than returning a single string. Here the function shapes the page title into a small JSON payload your application can consume directly.

## When you really need page.evaluate

Use `page.evaluate(...)` when the information only exists inside the live browser page:

``` js
const { data } = await mql(

  'https://developer.mozilla.org/en-US/docs/Web/API/Document/title',

  {

    function: `({ page }) => page.evaluate(() => ({

    heading: document.querySelector('main h1')?.textContent?.trim(),

    codeExamples: document.querySelectorAll('pre').length

  }))`,

    meta: false

  }

)

console.log(data.function.value)
```

That pattern is powerful, but it is also more fragile than `page.title()` or `page.$eval()`. Start with the page helpers first, then move into `page.evaluate(...)` when you need direct access to `document`, `window`, or browser-only APIs.

## Use npm packages

The function runtime can `require()` a curated allowlist of packages. That makes it useful for parsing, retries, HTML processing, HTTP calls, and response shaping without running your own serverless infrastructure.

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://developer.mozilla.org/en-US/docs/Web/API/Document/title' URL with 'function' & 'meta' API parameters:

### CLI Microlink API example

``` bash
microlink https://developer.mozilla.org/en-US/docs/Web/API/Document/title&function='({ page }) =>
  page.title().then(title => {
    const { words, kebabCase } = require('"'"'lodash'"'"')
    return {
      title,
      words: words(title),
      slug: kebabCase(title)
    }
  })'
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://developer.mozilla.org/en-US/docs/Web/API/Document/title" \
  -d "function=(%7B%20page%20%7D)%20%3D%3E%0A%20%20page.title().then(title%20%3D%3E%20%7B%0A%20%20%20%20const%20%7B%20words%2C%20kebabCase%20%7D%20%3D%20require('lodash')%0A%20%20%20%20return%20%7B%0A%20%20%20%20%20%20title%2C%0A%20%20%20%20%20%20words%3A%20words(title)%2C%0A%20%20%20%20%20%20slug%3A%20kebabCase(title)%0A%20%20%20%20%7D%0A%20%20%7D)" \
  -d "meta=false"
```

### JavaScript Microlink API example

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

const { data } = await mql('https://developer.mozilla.org/en-US/docs/Web/API/Document/title', {
  function: "({ page }) =>
  page.title().then(title => {
    const { words, kebabCase } = require('lodash')
    return {
      title,
      words: words(title),
      slug: kebabCase(title)
    }
  })",
  meta: false
})
```

### Python Microlink API example

``` python
import requests

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

querystring = {
    "url": "https://developer.mozilla.org/en-US/docs/Web/API/Document/title",
    "function": '''({ page }) =>
  page.title().then(title => {
    const { words, kebabCase } = require('lodash')
    return {
      title,
      words: words(title),
      slug: kebabCase(title)
    }
  })''',
    "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://developer.mozilla.org/en-US/docs/Web/API/Document/title",
  function: "({ page }) =>
  page.title().then(title => {
    const { words, kebabCase } = require('lodash')
    return {
      title,
      words: words(title),
      slug: kebabCase(title)
    }
  })",
  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://developer.mozilla.org/en-US/docs/Web/API/Document/title",
    "function" => "({ page }) =>
  page.title().then(title => {
    const { words, kebabCase } = require('lodash')
    return {
      title,
      words: words(title),
      slug: kebabCase(title)
    }
  })",
    "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.title().then(title => {
    const { words, kebabCase } = require('lodash')
    return {
      title,
      words: words(title),
      slug: kebabCase(title)
    }
  })`

    q := u.Query()
    q.Set("url", "https://developer.mozilla.org/en-US/docs/Web/API/Document/title")
    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://developer.mozilla.org/en-US/docs/Web/API/Document/title', {

  function: "({ page }) =>

  page.title().then(title => {

    const { words, kebabCase } = require('lodash')

    return {

      title,

      words: words(title),

      slug: kebabCase(title)

    }

  })",

  meta: false

})
```

The outer function can use allowed packages such as `lodash`. Here it turns the page title into both an array of words and a slug-like string.

Common choices include `cheerio`, `lodash`, `got`, `jsdom`, `@mozilla/readability`, `ioredis`, and `metascraper`. See the [function reference](https://microlink.io/docs/api/parameters/function) for the documented allowlist.

Most function-only workflows do not need normalized metadata such as title, description, image, or logo. In those cases, set `meta: false`:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://developer.mozilla.org/en-US/docs/Web/API/Document/title' URL with 'function' & 'meta' API parameters:

### CLI Microlink API example

``` bash
microlink https://developer.mozilla.org/en-US/docs/Web/API/Document/title&function='({ page }) => page.title()'
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -d "url=https://developer.mozilla.org/en-US/docs/Web/API/Document/title" \
  -d "function=(%7B%20page%20%7D)%20%3D%3E%20page.title()" \
  -d "meta=false"
```

### JavaScript Microlink API example

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

const { data } = await mql('https://developer.mozilla.org/en-US/docs/Web/API/Document/title', {
  function: "({ page }) => page.title()",
  meta: false
})
```

### Python Microlink API example

``` python
import requests

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

querystring = {
    "url": "https://developer.mozilla.org/en-US/docs/Web/API/Document/title",
    "function": "({ page }) => page.title()",
    "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://developer.mozilla.org/en-US/docs/Web/API/Document/title",
  function: "({ page }) => page.title()",
  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://developer.mozilla.org/en-US/docs/Web/API/Document/title",
    "function" => "({ page }) => page.title()",
    "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://developer.mozilla.org/en-US/docs/Web/API/Document/title")
    q.Set("function", "({ page }) => page.title()")
    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://developer.mozilla.org/en-US/docs/Web/API/Document/title', {

  function: "({ page }) => page.title()",

  meta: false

})
```

Disabling metadata is usually the biggest speedup for function requests. If you still need the rendered markup, call `page.content()` inside the function instead of enabling metadata just to read the page HTML.

## Compress large functions

When the function body gets too large for a comfortable query string, compress it before sending it:

``` js
const { compressToURI } = require('lz-ts')

const mql = require('@microlink/mql')

const code = ({ page }) => page.title()

const { data } = await mql(

  'https://developer.mozilla.org/en-US/docs/Web/API/Document/title',

  {

    function: `lz#${compressToURI(code.toString())}`,

    meta: false

  }

)

console.log(data.function.value)
```

Prefix the compressed payload with the algorithm alias:

- `lz#` for lz-string
- `br#` for brotli
- `gz#` for gzip

## Free tier, API key, and local testing

The free endpoint is enough to prototype function workflows and run the examples in this guide. If the same request also needs parameters such as `headers`, `proxy`, `ttl`, or `staleTtl`, those controls require a

PRO

plan.

To authenticate, pass your API key as `x-api-key`:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://developer.mozilla.org/en-US/docs/Web/API/Document/title' URL with 'function', 'meta' & 'apiKey' API parameters:

### CLI Microlink API example

``` bash
microlink https://developer.mozilla.org/en-US/docs/Web/API/Document/title&function='({ page }) => page.title()' --api-key YOUR_API_TOKEN
```

### cURL Microlink API example

``` bash
curl -G "https://api.microlink.io" \
  -H "x-api-key: YOUR_API_TOKEN" \
  -d "url=https://developer.mozilla.org/en-US/docs/Web/API/Document/title" \
  -d "function=(%7B%20page%20%7D)%20%3D%3E%20page.title()" \
  -d "meta=false"
```

### JavaScript Microlink API example

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

const { data } = await mql('https://developer.mozilla.org/en-US/docs/Web/API/Document/title', {
  function: "({ page }) => page.title()",
  meta: false,
  apiKey: "YOUR_API_TOKEN"
})
```

### Python Microlink API example

``` python
import requests

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

querystring = {
    "url": "https://developer.mozilla.org/en-US/docs/Web/API/Document/title",
    "function": "({ page }) => page.title()",
    "meta": "false"
}

headers = {
    "x-api-key": "YOUR_API_TOKEN"
}

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

print(response.json())
```

### Ruby Microlink API example

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

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

params = {
  url: "https://developer.mozilla.org/en-US/docs/Web/API/Document/title",
  function: "({ page }) => page.title()",
  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)
request['x-api-key'] = "YOUR_API_TOKEN"
response = http.request(request)

puts response.body
```

### PHP Microlink API example

``` php
<?php

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

$params = [
    "url" => "https://developer.mozilla.org/en-US/docs/Web/API/Document/title",
    "function" => "({ page }) => page.title()",
    "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",
    CURLOPT_HTTPHEADER => [
        "x-api-key: YOUR_API_TOKEN"
    ]
]);

$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://developer.mozilla.org/en-US/docs/Web/API/Document/title")
    q.Set("function", "({ page }) => page.title()")
    q.Set("meta", "false")
    u.RawQuery = q.Encode()

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

    req.Header.Set("x-api-key", "YOUR_API_TOKEN")

    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://developer.mozilla.org/en-US/docs/Web/API/Document/title', {

  function: "({ page }) => page.title()",

  meta: false,

  apiKey: "YOUR_API_TOKEN"

})
```

You can enter your API key in interactive examples by clicking the key icon in the terminal toolbar.

For local development, test the same function logic with [](https://github.com/microlinkhq/local)

[@microlink/local](https://github.com/microlinkhq/local)

. It is useful when you want to iterate on browser automation locally before sending the request to the hosted API.

See the [authentication](https://microlink.io/docs/api/basics/authentication) and [rate limit](https://microlink.io/docs/api/basics/rate-limit) docs for the exact endpoint and quota details.

## Common failure modes

These are the two function-specific errors you will hit most often:

- `EINVALFUNCTION` — the function string has invalid JavaScript syntax. Check quotes, brackets, template strings, and arrow function formatting.
- `EINVALEVAL` — the function executed but threw at runtime. Check undefined variables, DOM queries that return `null`, or mistakes inside `page.evaluate`.

If a function request starts getting slow or flaky:

1.  Reduce it to a trivial check such as `({ page }) => page.title()`.
2.  Set `meta: false` unless metadata is part of the requirement.
3.  Replace fixed waits with `waitForSelector` whenever possible.
4.  Move DOM-only code into `page.evaluate`, and keep orchestration in the outer function.

For timeouts, blocked sites, auth issues, and debug headers that apply to every workflow, see [common troubleshooting](https://microlink.io/docs/guides/common/troubleshooting).

## What's next

Pick the next page based on what is blocking you now:

- **[Common troubleshooting](https://microlink.io/docs/guides/common/troubleshooting)** — debug timeouts, blocked sites, and plan/auth problems.
- **[Common caching patterns](https://microlink.io/docs/guides/common/caching)** — reduce cost and improve response speed once the function logic is stable.
- **[Common private pages](https://microlink.io/docs/guides/common/private-pages)** — run functions against logged-in, session-based, or personalized pages safely.
- **[Production patterns](https://microlink.io/docs/guides/common/production-patterns)** — add retries, endpoint selection, and monitoring for real integrations.

## See also

- [Data extraction](https://microlink.io/docs/guides/data-extraction) — if declarative rules are enough and you want the simplest possible extraction workflow.
- [Screenshot: page interaction](https://microlink.io/docs/guides/screenshot/page-interaction) — if you mainly need to prepare a page before taking a screenshot.
- [PDF: page preparation](https://microlink.io/docs/guides/pdf/page-preparation) — if your real goal is to clean up or wait for the page before printing to PDF.