The Puppeteer alternative with no Chrome to run
Keep the Puppeteer code and drop the browser fleet. Send a function that receives a Puppeteer page, or ask for a screenshot or PDF by parameter, and Microlink runs it in a fresh Chrome on its side.
The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://news.ycombinator.com' URL with 'function' & 'meta' API parameters:
CLI Microlink API example
microlink https://news.ycombinator.com&function='({ page }) =>
page.$$eval('"'"'.titleline > a'"'"', links =>
links.slice(0, 5).map(a => ({ title: a.textContent, url: a.href }))
)'cURL Microlink API example
curl -G "https://api.microlink.io" \
-d "url=https://news.ycombinator.com" \
-d "function=(%7B%20page%20%7D)%20%3D%3E%0A%20%20page.%24%24eval('.titleline%20%3E%20a'%2C%20links%20%3D%3E%0A%20%20%20%20links.slice(0%2C%205).map(a%20%3D%3E%20(%7B%20title%3A%20a.textContent%2C%20url%3A%20a.href%20%7D))%0A%20%20)" \
-d "meta=false"JavaScript Microlink API example
import createClient from 'microlink.io'
const microlink = createClient()
const { value } = await microlink.function(
'https://news.ycombinator.com',
({ page }) =>
page.$$eval('.titleline > a', links =>
links.slice(0, 5).map(a => ({ title: a.textContent, url: a.href }))
)
)Python Microlink API example
import requests
url = "https://api.microlink.io/"
querystring = {
"url": "https://news.ycombinator.com",
"function": '''({ page }) =>
page.$$eval('.titleline > a', links =>
links.slice(0, 5).map(a => ({ title: a.textContent, url: a.href }))
)''',
"meta": "false"
}
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: "({ page }) =>
page.$$eval('.titleline > a', links =>
links.slice(0, 5).map(a => ({ title: a.textContent, url: a.href }))
)",
meta: "false"
}
uri = URI(base_url)
uri.query = URI.encode_www_form(params)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri)
response = http.request(request)
puts response.bodyPHP Microlink API example
<?php
$baseUrl = "https://api.microlink.io/";
$params = [
"url" => "https://news.ycombinator.com",
"function" => "({ page }) =>
page.$$eval('.titleline > a', links =>
links.slice(0, 5).map(a => ({ title: a.textContent, url: a.href }))
)",
"meta" => "false"
];
$query = http_build_query($params);
$url = $baseUrl . '?' . $query;
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET"
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #: " . $err;
} else {
echo $response;
}Golang Microlink API example
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('.titleline > a', links =>
links.slice(0, 5).map(a => ({ title: a.textContent, url: a.href }))
)`
q := u.Query()
q.Set("url", "https://news.ycombinator.com")
q.Set("function", fn)
q.Set("meta", "false")
u.RawQuery = q.Encode()
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
panic(err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}import createClient from 'microlink.io'
const microlink = createClient()
const { value } = await microlink.function(
'https://news.ycombinator.com',
({ page }) =>
page.$$eval('.titleline > a', links =>
links.slice(0, 5).map(a => ({ title: a.textContent, url: a.href }))
)
)What you own when you run Puppeteer.
npm install puppeteer and a ten-line script work on a laptop. Production adds a binary, a runtime and a process tree to look after. Every number below comes from the Puppeteer, AWS or Chromium docs, or from the @sparticuz/chromium repository.| The job | Running Puppeteer yourself | Microlink |
|---|---|---|
| The browser binary | Chrome for Testing downloads on install: about 170 MB on macOS, 282 MB on Linux, 280 MB on Windows. | Nothing to download. Your code makes an HTTP call. |
| Version upgrades | Each Puppeteer release pairs with one Chrome build (v25.17.0 with 157.0.8103.50), and Chrome ships a new major version every two weeks. | Chrome and Puppeteer upgraded on our side. |
| Serverless packaging | Lambda caps a zip deployment at 250 MB unzipped, layers included, and the Linux browser alone is larger. Either ship a container image (10 GB cap) and pay a larger cold start, or swap in the 130.62 MiB @sparticuz/chromium build. | No layer, no package budget to fit. |
| System libraries and fonts | Chrome for Testing ships without its shared library dependencies. The Lambda runtime has no fonts, and the common trimmed build adds Open Sans only, no emoji. | Fonts and libraries installed once, for every call. |
| Zombie processes | Puppeteer’s own troubleshooting guide points to dumb-init or docker --init to reap Chrome processes left behind. | A fresh browser per call, destroyed when the response is sent. |
| Concurrency and queueing | You size the pool: how many browsers per box, how many pages per browser, what waits in the queue. | Paid plans are capped by quota, never by rate. Free keys allow 2 calls in flight. |
| Cold starts | Every new container or function launches Chrome before the first page loads. | Your code launches no browser. Cache hits skip the browser entirely. |
| Proxies and antibot | You buy a proxy pool, rotate it, and detect blocks yourself. | Proxy resolution included on Pro, and blocks named by provider. |
| Caching and retries | You build a cache in front of the browser and a retry loop around it. | ttl from 1 minute to 31 days, and 2 backoff retries by default. |
Download sizes from the Puppeteer installation guide; version pairing from supported browsers; release cadence from the Chromium release cycle doc; the 250 MB zip and 10 GB container image limits from AWS Lambda quotas; the trimmed build size and font list from @sparticuz/chromium; libraries and zombie processes from Puppeteer troubleshooting. The Microlink column links to ttl, retry, proxy and request isolation. Last verified: November 2026.
Send the page code Skip the browser fleet
2.8
secs
P95 screenshot
1.6
secs
P95 PDF
99.9
%
SLA Guaranteed
Start free, scale when ready
One request per call, whether it runs your function, takes a screenshot or prints a PDF. The rate holds at $1.07 per thousand calls whichever tier you pick, and a cache hit costs nothing.
Free
Every Pro feature. No card.
$0/month
25 requests per day
Pro
For production workloads.
$49/month
≈ $1.07 per 1,000 requests
46,000 requests / month
- Everything in Free
- Automatic proxy resolution
- Configurable TTL
- Custom HTTP headers
- Custom cache key
- Priority email support
Cancel anytime · No setup fees
Business & Enterprise
Bought the way companies buy.
- Everything in Pro, plus:
- Card or invoice, PO number, net 30
- NDA, DPA & service agreement
- Vendor assessments on request
- Same named contact
- Annual billing, 10% discount
Enterprise adds
Build or buy, row by row.
Both run the same engine: Chrome, driven over the DevTools Protocol by Puppeteer. Microlink builds on browserless, its open-source driver on top of Puppeteer. The difference is who operates the browser. Puppeteer facts come from pptr.dev and the Puppeteer repository, and the last four rows are where running it yourself wins.
| Capability | Microlink | Self-hosted Puppeteer |
|---|---|---|
| Run your own Puppeteer code function receives page, a full Puppeteer Page already navigated to the URL, plus response and headers. Paid plans allow 60 seconds and 128 MB per run. | ✓ | ✓ |
| Chrome install and upgrades Puppeteer pairs each release with one Chrome for Testing build, and Chrome ships a major version every two weeks. | Managed | You pin and upgrade |
| Install footprint Lambda caps a zip deployment at 250 MB unzipped, layers included, and a container image at 10 GB. | 0 MB | ~282 MB on Linux |
| Fresh browser per call No cookies or storage carry over between Microlink calls. In Puppeteer, a new browser context shares no cookies or cache with the others. | ✓ | createBrowserContext() per job |
| Screenshot, PDF, metadata, markdown page.screenshot() and page.pdf() exist in Puppeteer. Metadata and markdown are code you write and maintain. | One parameter each | You write each |
| Response caching Default ttl is 24 hours, and a cache hit is not counted against the plan. | 1 minute to 31 days | Your code |
| Retries Exponential backoff when the browser fails internally. | 2 by default | Your code |
| Ads and cookie banners Puppeteer blocks requests through page.setRequestInterception() and rules you maintain. | Blocked by default | Write interception rules |
| Proxy for blocked targets proxy.location pins the exit country; proxy.url routes through a server you supply. | Included on Pro | Bring your own |
| Antibot detection Microlink names the provider that blocked the request. | ✓ | Your code |
| Free tier Without signing up you get 5 calls daily; a free key raises that to 25, no card asked. Puppeteer costs nothing to install, while the machine behind it bills by the hour. | 25/day | Free, Apache-2.0 |
| Session length A browser you launch stays open as long as your process does. | 60 s per call | Unbounded |
| Private network and localhost Microlink refuses private and loopback targets with EFORBIDDENURL. | ✕ | ✓ |
| Firefox Puppeteer drives stable Firefox since v23.0.0. Microlink runs Chrome only. | ✕ | ✓ |
| Launch flags and extensions puppeteer.launch() takes any Chrome flag. Microlink launches the browser for you. | ✕ | ✓ |
Last verified: November 2026. Check pptr.dev for the latest Puppeteer and Chrome versions.
When running Puppeteer yourself is the better pick.
An API is the wrong tool for some Puppeteer jobs. Six of them, stated plainly.
Long sessions that keep state
A login, then fifty clicks, then a download, all in one browser that stays open for an hour. Microlink gives each call a fresh browser and a 60-second ceiling on paid plans, so state across calls is yours to carry.End-to-end tests
Tests want the browser next to the code under test, deterministic and offline, running in CI. Puppeteer, or a test runner built on it, is the right tool there.Intranet and localhost targets
Microlink only resolves public addresses and refuses private and loopback ones with EFORBIDDENURL. A dev server, a staging box behind a VPN or an internal dashboard needs a browser inside that network.Very high, steady volume
At millions of pages a month on a flat, predictable load, a dedicated box can cost less per page than $1.07 per 1,000 requests. Count the hours spent keeping it up before you decide: self-hosting is cheaper only if it still wins with them included.Latency-critical paths with a warm pool
Microlink launches a fresh browser for every call, so a screenshot takes the P95 shown on this page. A Puppeteer browser you keep running answers browser.newPage() in-process with no launch at all, which is far faster when every millisecond sits in front of a user.Full control of the browser
Custom launch flags, extensions, a specific Chrome build or Firefox. puppeteer.launch() takes all of it; Microlink chooses the browser and its flags for you.
Product Information
What moves to the API, what stays in your code, and where the limits are.
Can I run my existing Puppeteer script on Microlink?
Mostly as is. Remove
puppeteer.launch() and page.goto(), take page from the function arguments and return the result. Everything after navigation, from page.click() to page.$$eval(), works unchanged because page is a full Puppeteer Page. The function can require() npm packages, and the result comes back under data.function. See function and writing functions.Which browser runs my code?
Chrome. Microlink drives it through browserless, its open-source driver on top of Puppeteer, and keeps Chrome as the engine because the same rendering produces the screenshots, PDFs and DOM the API returns. Firefox is not available. Read why we still run Chrome.
What are the limits of a function call?
On paid plans a function gets 60 seconds, 128 MB of memory, unlimited code size and unrestricted outgoing requests. On the free plan it gets 15 seconds, 64 MB, 1024 bytes of code, 2 concurrent requests and same-origin requests only. Hitting a limit returns a named error such as
TimeoutError instead of failing the whole request. See function troubleshooting.Why not run Puppeteer on AWS Lambda?
You can, with work. Lambda caps a zip deployment at 250 MB unzipped including layers (AWS quotas), and the Chrome for Testing build Puppeteer downloads is about 282 MB on Linux (Puppeteer docs). One path is a container image, which Lambda accepts up to 10 GB, at the price of a larger cold start. The other is a trimmed build such as @sparticuz/chromium, with fonts added through a layer because the runtime ships none. Either way every cold start pays a browser launch.
How does pricing compare to running my own servers?
Every self-serve tier works out to $1.07 per thousand calls: $49 buys 46,000 a month and $450 buys 420,000, with cache hits billed at zero. A server bills a fixed amount each month, and on top of it come the hours spent upgrading Chrome, fixing fonts and reaping processes. Low or spiky traffic usually favors the API; very high, steady traffic can favor your own box, once those hours are counted.
Can I try it without a credit card?
Yes. 5 requests a day need no key at all, and the free API key renews 25 requests every day with no card. Function, screenshot, PDF, metadata and markdown are all included on it.
Start building
Paste the body of the Puppeteer script you run today into a function call and compare the result.
Get your free API key25 requests/day · Every Pro feature · No credit card
Puppeteer, Chrome and Chromium are trademarks of Google LLC. Microlink is not affiliated with or endorsed by Google. Details about Puppeteer, Chrome and AWS Lambda come from their public documentation and may have changed since they were checked.