Skip to content

Browser Function
as a Service

Write a JavaScript function. Send a URL. Microlink runs the function remotely and returns whatever it returned — no Lambda, no browser fleet, no server to operate.

Send a function
Get the result

You write a normal JavaScript function. Microlink serializes it, runs it in a sandbox, and sends back the return value. A browser starts only if the function uses page.

How Microlink Function runsYou send function code and a target URL. Microlink runs that code on the page and returns whatever it produced. A browser starts only if you need the page.INPUTOUTPUTEVALFETCHVALUEFunction codeTarget URLMicrolinkResult
  • Write a function

    Any JavaScript. Return a number, a string, an array, or an object. No Lambda bundle and no special format — the same function you would run locally.
  • Send it with a URL

    The function runs against that page. Mention page and Microlink starts a headless browser and gives you the full Puppeteer page object. Skip page and no browser starts.
  • Read the return value

    value is what the function returned. isFulfilled is false if it threw, and value then holds the error. profiling.phases shows install, build, spawn, and run.

How a function runs

Start with a function that returns a value. Add a browser, a click, or a package only when you need them.

Your first function

Pass a JavaScript function and a target URL. The function runs remotely. The return value is at value — the same way a local function returns.

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

CLI Microlink API example

microlink https://example.com&function='({ page }) => page.title()'

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://example.com" \
  -d "function=(%7B%20page%20%7D)%20%3D%3E%20page.title()"

JavaScript Microlink API example

import createClient from 'microlink.io'

const microlink = createClient()

const { value } = await microlink.run(
  'https://example.com',
  ({ page }) => page.title()
)

Python Microlink API example

import requests

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

querystring = {
    "url": "https://example.com",
    "function": "({ page }) => page.title()"
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://example.com",
  function: "({ page }) => page.title()"
}

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

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

$params = [
    "url" => "https://example.com",
    "function" => "({ page }) => page.title()"
];

$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

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("function", "({ page }) => page.title()")
    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))
}

Skip the browser when you can

When the function does not mention page, no Chrome starts. That is faster and cheaper. Extra parameters on the request are forwarded to the function, so one function can be reused.

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

CLI Microlink API example

microlink https://example.com&function='() => 40 + 2'

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://example.com" \
  -d "function=()%20%3D%3E%2040%20%2B%202"

JavaScript Microlink API example

import createClient from 'microlink.io'

const microlink = createClient()

const { value } = await microlink.run('https://example.com', () => 40 + 2)

Python Microlink API example

import requests

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

querystring = {
    "url": "https://example.com",
    "function": "() => 40 + 2"
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://example.com",
  function: "() => 40 + 2"
}

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

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

$params = [
    "url" => "https://example.com",
    "function" => "() => 40 + 2"
];

$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

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("function", "() => 40 + 2")
    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))
}

Read the result

A throw does not fail the HTTP request. isFulfilled tells you if the function finished. value is the return, or the error. profiling.phases shows where time went.

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

CLI Microlink API example

microlink https://example.com&function='() => { throw new Error("boom") }'

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://example.com" \
  -d "function=()%20%3D%3E%20%7B%20throw%20new%20Error(%22boom%22)%20%7D"

JavaScript Microlink API example

import createClient from 'microlink.io'

const microlink = createClient()

const { value } = await microlink.run(
  'https://example.com',
  () => { throw new Error("boom") }
)

Python Microlink API example

import requests

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

querystring = {
    "url": "https://example.com",
    "function": '''() => { throw new Error("boom") }'''
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://example.com",
  function: '() => { throw new Error("boom") }'
}

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

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

$params = [
    "url" => "https://example.com",
    "function" => '() => { throw new Error("boom") }'
];

$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

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 := `() => { throw new Error("boom") }`

    q := u.Query()
    q.Set("url", "https://example.com")
    q.Set("function", fn)
    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))
}

Prefer extract() first

If a CSS selector is enough, do not write a function. data is shorter, cheaper, and easier to reuse. Reach for Function when the first HTML is not the data.

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

CLI Microlink API example

microlink https://microlink.io&data.title.selector=title&data.description.selector='meta[name="description"]'&data.description.attr=content

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://microlink.io" \
  -d "data.title.selector=title" \
  -d "data.description.selector=meta[name="description"]" \
  -d "data.description.attr=content"

JavaScript Microlink API example

import createClient from 'microlink.io'

const microlink = createClient()

const { title, description } = await microlink.extract('https://microlink.io', {
  title: {
    selector: "title"
  },
  description: {
    selector: 'meta[name="description"]',
    attr: "content"
  }
})

Python Microlink API example

import requests

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

querystring = {
    "url": "https://microlink.io",
    "data.title.selector": "title",
    "data.description.selector": '''meta[name="description"]''',
    "data.description.attr": "content"
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://microlink.io",
  data.title.selector: "title",
  data.description.selector: 'meta[name="description"]',
  data.description.attr: "content"
}

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

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

$params = [
    "url" => "https://microlink.io",
    "data.title.selector" => "title",
    "data.description.selector" => 'meta[name="description"]',
    "data.description.attr" => "content"
];

$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

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)
    }
    data.description.selectorParam := `meta[name="description"]`

    q := u.Query()
    q.Set("url", "https://microlink.io")
    q.Set("data.title.selector", "title")
    q.Set("data.description.selector", data.description.selectorParam)
    q.Set("data.description.attr", "content")
    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))
}

page is a remote Chrome

Name page and Microlink navigates first, then hands you the Puppeteer page object. title, $eval, $$eval, click, wait — the same API you use locally.

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

CLI Microlink API example

microlink https://microlink.io&function='({ page }) => page.evaluate(() => ({
  title: document.title,
  links: document.links.length,
  resources: performance.getEntriesByType('"'"'resource'"'"').length
}))'

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://microlink.io" \
  -d "function=(%7B%20page%20%7D)%20%3D%3E%20page.evaluate(()%20%3D%3E%20(%7B%0A%20%20title%3A%20document.title%2C%0A%20%20links%3A%20document.links.length%2C%0A%20%20resources%3A%20performance.getEntriesByType('resource').length%0A%7D))"

JavaScript Microlink API example

import createClient from 'microlink.io'

const microlink = createClient()

const { value } = await microlink.run(
  'https://microlink.io',
  ({ page }) => page.evaluate(() => ({
    title: document.title,
    links: document.links.length,
    resources: performance.getEntriesByType('resource').length
  }))
)

Python Microlink API example

import requests

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

querystring = {
    "url": "https://microlink.io",
    "function": '''({ page }) => page.evaluate(() => ({
  title: document.title,
  links: document.links.length,
  resources: performance.getEntriesByType('resource').length
}))'''
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://microlink.io",
  function: "({ page }) => page.evaluate(() => ({
  title: document.title,
  links: document.links.length,
  resources: performance.getEntriesByType('resource').length
}))"
}

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

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

$params = [
    "url" => "https://microlink.io",
    "function" => "({ page }) => page.evaluate(() => ({
  title: document.title,
  links: document.links.length,
  resources: performance.getEntriesByType('resource').length
}))"
];

$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

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(() => ({
  title: document.title,
  links: document.links.length,
  resources: performance.getEntriesByType('resource').length
}))`

    q := u.Query()
    q.Set("url", "https://microlink.io")
    q.Set("function", fn)
    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))
}

Click, wait, then scrape

Pagination, “Load more”, and client-rendered lists are missing from the first HTML. Click, wait for the new nodes, then return the text or hrefs.

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' API parameter:

CLI Microlink API example

microlink https://news.ycombinator.com&function='async ({ page }) => {
  await page.click('"'"'a.morelink'"'"')
  await page.waitForSelector('"'"'.athing'"'"')
  return page.$$eval('"'"'.titleline a'"'"', els =>
    els.map(el => el.textContent)
  )
}'

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://news.ycombinator.com" \
  -d "function=async%20(%7B%20page%20%7D)%20%3D%3E%20%7B%0A%20%20await%20page.click('a.morelink')%0A%20%20await%20page.waitForSelector('.athing')%0A%20%20return%20page.%24%24eval('.titleline%20a'%2C%20els%20%3D%3E%0A%20%20%20%20els.map(el%20%3D%3E%20el.textContent)%0A%20%20)%0A%7D"

JavaScript Microlink API example

import createClient from 'microlink.io'

const microlink = createClient()

const { value } = await microlink.run(
  'https://news.ycombinator.com',
  async ({ page }) => {
    await page.click('a.morelink')
    await page.waitForSelector('.athing')
    return page.$$eval('.titleline a', els =>
      els.map(el => el.textContent)
    )
  }
)

Python Microlink API example

import requests

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

querystring = {
    "url": "https://news.ycombinator.com",
    "function": '''async ({ page }) => {
  await page.click('a.morelink')
  await page.waitForSelector('.athing')
  return page.$$eval('.titleline a', els =>
    els.map(el => el.textContent)
  )
}'''
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://news.ycombinator.com",
  function: "async ({ page }) => {
  await page.click('a.morelink')
  await page.waitForSelector('.athing')
  return page.$$eval('.titleline a', els =>
    els.map(el => el.textContent)
  )
}"
}

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

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

$params = [
    "url" => "https://news.ycombinator.com",
    "function" => "async ({ page }) => {
  await page.click('a.morelink')
  await page.waitForSelector('.athing')
  return page.$$eval('.titleline a', els =>
    els.map(el => el.textContent)
  )
}"
];

$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

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 := `async ({ page }) => {
  await page.click('a.morelink')
  await page.waitForSelector('.athing')
  return page.$$eval('.titleline a', els =>
    els.map(el => el.textContent)
  )
}`

    q := u.Query()
    q.Set("url", "https://news.ycombinator.com")
    q.Set("function", fn)
    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))
}

require() a package

Need cheerio or lodash? require it. The runtime detects the import, installs it in the sandbox, and caches it. No Lambda zip. Pin a version with require('[email protected]').

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://microlink.io/blog' URL with 'function' API parameter:

CLI Microlink API example

microlink https://microlink.io/blog&function='async ({ page }) => {
  const cheerio = require('"'"'cheerio'"'"')
  const $ = cheerio.load(await page.content())
  return $('"'"'article'"'"').map((i, el) => ({
    title: $(el).find('"'"'h2, h3'"'"').first().text(),
    href: $(el).find('"'"'a'"'"').attr('"'"'href'"'"')
  })).get()
}'

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://microlink.io/blog" \
  -d "function=async%20(%7B%20page%20%7D)%20%3D%3E%20%7B%0A%20%20const%20cheerio%20%3D%20require('cheerio')%0A%20%20const%20%24%20%3D%20cheerio.load(await%20page.content())%0A%20%20return%20%24('article').map((i%2C%20el)%20%3D%3E%20(%7B%0A%20%20%20%20title%3A%20%24(el).find('h2%2C%20h3').first().text()%2C%0A%20%20%20%20href%3A%20%24(el).find('a').attr('href')%0A%20%20%7D)).get()%0A%7D"

JavaScript Microlink API example

import createClient from 'microlink.io'

const microlink = createClient()

const { value } = await microlink.run(
  'https://microlink.io/blog',
  async ({ page }) => {
    const cheerio = require('cheerio')
    const $ = cheerio.load(await page.content())
    return $('article').map((i, el) => ({
      title: $(el).find('h2, h3').first().text(),
      href: $(el).find('a').attr('href')
    })).get()
  }
)

Python Microlink API example

import requests

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

querystring = {
    "url": "https://microlink.io/blog",
    "function": '''async ({ page }) => {
  const cheerio = require('cheerio')
  const $ = cheerio.load(await page.content())
  return $('article').map((i, el) => ({
    title: $(el).find('h2, h3').first().text(),
    href: $(el).find('a').attr('href')
  })).get()
}'''
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://microlink.io/blog",
  function: "async ({ page }) => {
  const cheerio = require('cheerio')
  const $ = cheerio.load(await page.content())
  return $('article').map((i, el) => ({
    title: $(el).find('h2, h3').first().text(),
    href: $(el).find('a').attr('href')
  })).get()
}"
}

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

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

$params = [
    "url" => "https://microlink.io/blog",
    "function" => "async ({ page }) => {
  const cheerio = require('cheerio')
  const $ = cheerio.load(await page.content())
  return $('article').map((i, el) => ({
    title: $(el).find('h2, h3').first().text(),
    href: $(el).find('a').attr('href')
  })).get()
}"
];

$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

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 := `async ({ page }) => {
  const cheerio = require('cheerio')
  const $ = cheerio.load(await page.content())
  return $('article').map((i, el) => ({
    title: $(el).find('h2, h3').first().text(),
    href: $(el).find('a').attr('href')
  })).get()
}`

    q := u.Query()
    q.Set("url", "https://microlink.io/blog")
    q.Set("function", fn)
    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))
}

Inject a script

Function is another Microlink parameter, so you can prepare the page first. Pass scripts and the helper lands before the function runs.

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

CLI Microlink API example

microlink https://microlink.io&function='({ page }) => page.evaluate(() =>
  $('"'"'a[href^="/docs"]'"'"').map((i, el) => el.href).get()
)'&scripts=https://code.jquery.com/jquery-3.5.0.min.js

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://microlink.io" \
  -d "function=(%7B%20page%20%7D)%20%3D%3E%20page.evaluate(()%20%3D%3E%0A%20%20%24('a%5Bhref%5E%3D%22%2Fdocs%22%5D').map((i%2C%20el)%20%3D%3E%20el.href).get()%0A)" \
  -d "scripts=https://code.jquery.com/jquery-3.5.0.min.js"

JavaScript Microlink API example

import createClient from 'microlink.io'

const microlink = createClient()

const { value } = await microlink.run(
  'https://microlink.io',
  ({ page }) => page.evaluate(() =>
    $('a[href^="/docs"]').map((i, el) => el.href).get()
  ),
  {
    scripts: "https://code.jquery.com/jquery-3.5.0.min.js"
  }
)

Python Microlink API example

import requests

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

querystring = {
    "url": "https://microlink.io",
    "function": '''({ page }) => page.evaluate(() =>
  $('a[href^="/docs"]').map((i, el) => el.href).get()
)''',
    "scripts": "https://code.jquery.com/jquery-3.5.0.min.js"
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://microlink.io",
  function: "({ page }) => page.evaluate(() =>
  $('a[href^=\"/docs\"]').map((i, el) => el.href).get()
)",
  scripts: "https://code.jquery.com/jquery-3.5.0.min.js"
}

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

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

$params = [
    "url" => "https://microlink.io",
    "function" => "({ page }) => page.evaluate(() =>
  $('a[href^=\"/docs\"]').map((i, el) => el.href).get()
)",
    "scripts" => "https://code.jquery.com/jquery-3.5.0.min.js"
];

$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

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(() =>
  $('a[href^="/docs"]').map((i, el) => el.href).get()
)`

    q := u.Query()
    q.Set("url", "https://microlink.io")
    q.Set("function", fn)
    q.Set("scripts", "https://code.jquery.com/jquery-3.5.0.min.js")
    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))
}

Route through a proxy

Datacenter IPs get blocked. Pin a country with proxy.location and the function runs after a residential navigation. Same value, harder target.

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

CLI Microlink API example

microlink https://github.com/microlinkhq/mql&function='async ({ page }) => {
  await page.waitForSelector('"'"'#repo-stars-counter-star'"'"')
  return page.$eval('"'"'#repo-stars-counter-star'"'"', el => el.title)
}'&proxy.location=us

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://github.com/microlinkhq/mql" \
  -d "function=async%20(%7B%20page%20%7D)%20%3D%3E%20%7B%0A%20%20await%20page.waitForSelector('%23repo-stars-counter-star')%0A%20%20return%20page.%24eval('%23repo-stars-counter-star'%2C%20el%20%3D%3E%20el.title)%0A%7D" \
  -d "proxy.location=us"

JavaScript Microlink API example

import createClient from 'microlink.io'

const microlink = createClient()

const { value } = await microlink.run(
  'https://github.com/microlinkhq/mql',
  async ({ page }) => {
    await page.waitForSelector('#repo-stars-counter-star')
    return page.$eval('#repo-stars-counter-star', el => el.title)
  },
  {
    proxy: {
      location: "us"
    }
  }
)

Python Microlink API example

import requests

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

querystring = {
    "url": "https://github.com/microlinkhq/mql",
    "function": '''async ({ page }) => {
  await page.waitForSelector('#repo-stars-counter-star')
  return page.$eval('#repo-stars-counter-star', el => el.title)
}''',
    "proxy.location": "us"
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://github.com/microlinkhq/mql",
  function: "async ({ page }) => {
  await page.waitForSelector('#repo-stars-counter-star')
  return page.$eval('#repo-stars-counter-star', el => el.title)
}",
  proxy.location: "us"
}

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

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

$params = [
    "url" => "https://github.com/microlinkhq/mql",
    "function" => "async ({ page }) => {
  await page.waitForSelector('#repo-stars-counter-star')
  return page.$eval('#repo-stars-counter-star', el => el.title)
}",
    "proxy.location" => "us"
];

$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

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 := `async ({ page }) => {
  await page.waitForSelector('#repo-stars-counter-star')
  return page.$eval('#repo-stars-counter-star', el => el.title)
}`

    q := u.Query()
    q.Set("url", "https://github.com/microlinkhq/mql")
    q.Set("function", fn)
    q.Set("proxy.location", "us")
    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))
}

Cache the result

Set ttl and a repeat of the same URL and function is served from the edge. The sandbox does not run again. Cache hits are free.

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

CLI Microlink API example

microlink https://example.com&function='({ page }) => page.$eval('"'"'h1'"'"', el => el.textContent)'&ttl=1h

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://example.com" \
  -d "function=(%7B%20page%20%7D)%20%3D%3E%20page.%24eval('h1'%2C%20el%20%3D%3E%20el.textContent)" \
  -d "ttl=1h"

JavaScript Microlink API example

import createClient from 'microlink.io'

const microlink = createClient()

const { value } = await microlink.run(
  'https://example.com',
  ({ page }) => page.$eval('h1', el => el.textContent),
  {
    ttl: "1h"
  }
)

Python Microlink API example

import requests

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

querystring = {
    "url": "https://example.com",
    "function": '''({ page }) => page.$eval('h1', el => el.textContent)''',
    "ttl": "1h"
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://example.com",
  function: "({ page }) => page.$eval('h1', el => el.textContent)",
  ttl: "1h"
}

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

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

$params = [
    "url" => "https://example.com",
    "function" => "({ page }) => page.$eval('h1', el => el.textContent)",
    "ttl" => "1h"
];

$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

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.$eval('h1', el => el.textContent)`

    q := u.Query()
    q.Set("url", "https://example.com")
    q.Set("function", fn)
    q.Set("ttl", "1h")
    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))
}

Start free, scale when ready

No signup, no API key, no credit card. Write a function and send it — 25 requests/day on the free plan.

Free

Try the API in seconds. No card.
$0/month
25 requests per day

Pro

For production workloads.
$49/month
$1.07 per 1,000 requests
46,000 requests / month
Cancel anytime · No setup fees

Enterprise

Dedicated infra for high-volume.
Custom
Tailored to your volume

What you can add

A function and a URL are enough to start. These are the options you can add on the same request.
  • Microlink Function

    Send a function and a URL. Read the return value.
  • Browser on demand

    Chrome starts only when the function uses page.
  • require() anything

    require() installs on the fly. No zip, no install step.
  • Click and paginate

    Click, wait, then return the new nodes.
  • Inject scripts

    scripts lands in the page before the function runs.
  • Residential proxy

    proxy.location pins a country for blocked targets.
  • TTL cache

    ttl serves the same call from cache. Hits are free.
  • Compression

    gzip, brotli, or zstd on the wire.
  • Errors as values

    A throw still resolves. Read isFulfilled and value.
  • Profiling

    profiling.phases breaks down install, build, spawn, run.
  • Scope

    Extra arguments become scope on the remote function.
  • TypeScript

    Types ship with the SDK. No extra package.
  • CLI and HTTP

    The same function from the SDK, CLI, or a GET.
  • API token

    Free is 25 requests/day. Pro raises the daily cap.
  • Edge cache

    A warm cache skips the sandbox on the next call.

Start now

Write a function. Send a URL. 25 requests/day, no account, no card.
No login needed
25 reqs/day free
No credit card

Product Information

The questions that come up the first time you send a function.

A way to run your JavaScript remotely. You send a function and a URL. Microlink executes the function in a sandbox — and starts a headless browser only if the function uses page — then returns the value. No Lambda bundle, no browser fleet, no server.

When does the function start a browser?

Only when your code references page. Without it, Microlink skips the headless browser entirely, so plain compute runs faster and cheaper. Reference page to get the full Puppeteer API for clicks, waits, and evaluation.

When should I use Function instead of extract()?

Start with extract() — declarative CSS-selector rules are shorter and easier to maintain.
Escalate to Function when you need to click, wait, compute, or orchestrate custom logic that rules cannot express.

Can I require() npm packages?

Yes. Any require() call is detected, installed on the fly into the sandbox, and cached for later runs. Pin a version with require('[email protected]'). Operations such as spawning child processes or writing outside the sandbox are not permitted.

What happens if my function throws?

The promise still resolves: result.isFulfilled comes back false and result.value carries the error as { name, message } so you handle failures in your own code.

Is Function available on the free plan?

Yes. Free runs get a 5-second timeout, 16 MB of memory, 1024 bytes of code, and one concurrent execution per IP. Pro plans extend the timeout up to 60 seconds, raise memory to 32 MB, and remove code-size and concurrency limits.

Does every call execute the function again?

Only on a cache miss. Set a ttl and any repeat request for the same URL and function inside that window is served from the edge cache instantly, at no cost and without running the sandbox again.