The Playwright alternative for production screenshots and PDFs
Playwright was built to test your own app across three browsers. Reused as a screenshot, PDF or scraping service, it brings browser builds per release, a Docker image to pin, workers to size and proxies to buy. Microlink runs that browser for you: one request, one URL, the file or the data back.
The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://playwright.dev' URL with 'screenshot', 'device' & 'meta' API parameters:
CLI Microlink API example
microlink https://playwright.dev&screenshot.fullPage&screenshot.type=jpeg&device='iPhone 15 Pro'cURL Microlink API example
curl -G "https://api.microlink.io" \
-d "url=https://playwright.dev" \
-d "screenshot.fullPage=true" \
-d "screenshot.type=jpeg" \
-d "device=iPhone%2015%20Pro" \
-d "meta=false"JavaScript Microlink API example
import createClient from 'microlink.io'
const microlink = createClient()
const data = await microlink.screenshot('https://playwright.dev', {
fullPage: true,
type: "jpeg",
device: "iPhone 15 Pro"
})Python Microlink API example
import requests
url = "https://api.microlink.io/"
querystring = {
"url": "https://playwright.dev",
"screenshot.fullPage": "true",
"screenshot.type": "jpeg",
"device": "iPhone 15 Pro",
"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://playwright.dev",
screenshot.fullPage: "true",
screenshot.type: "jpeg",
device: "iPhone 15 Pro",
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://playwright.dev",
"screenshot.fullPage" => "true",
"screenshot.type" => "jpeg",
"device" => "iPhone 15 Pro",
"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)
}
q := u.Query()
q.Set("url", "https://playwright.dev")
q.Set("screenshot.fullPage", "true")
q.Set("screenshot.type", "jpeg")
q.Set("device", "iPhone 15 Pro")
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 data = await microlink.screenshot('https://playwright.dev', {
fullPage: true,
type: "jpeg",
device: "iPhone 15 Pro"
})What the test runner leaves to you in production.
Browser builds per release
Each Playwright version needs specific browser binaries, installed with npx playwright install. They take a few hundred megabytes of disk, and every upgrade means installing them again.A Docker image to pin
The official image is tagged by Playwright version, and a mismatch leaves Playwright unable to find its browsers. The docs recommend --ipc=host, without which Chromium can run out of memory and crash, and --init to reap zombie processes.Untrusted pages need hardening
The Playwright docs advise against using its Docker image to visit untrusted websites. Scraping arbitrary URLs safely means a non-root user plus a seccomp profile to keep the Chromium sandbox on.Workers, memory and timeouts
A test suite runs on a schedule. A production service gets traffic spikes, pages that never reach networkidle and tabs that leak memory, so someone sizes workers, sets timeouts and restarts what hangs.Proxies and antibot
Your own staging server never blocks you. Production targets do, and Playwright ships no proxy pool or antibot detection: launch accepts a proxy server, and the rest is yours to buy and wire.Storage and caching
page.screenshot and page.pdf return a buffer or write a file. Hosting it, serving it from a CDN and deciding when to render it again are left to the caller.
Your Playwright calls, as parameters.
Most of a Playwright screenshot or PDF script configures one page, then captures it. Each of those calls has a Microlink query parameter, so the script becomes one request. Steps that need real code go to Function, which hands your code a Puppeteer page: Playwright locators and calls do not run there and have to be rewritten.
| What the script does | Playwright | Microlink |
|---|---|---|
| Full-page screenshot | page.screenshot({ fullPage: true }) | screenshot.fullPage |
| Screenshot one element | locator.screenshot() | screenshot.element |
| JPEG, quality, transparency | type, quality, omitBackground | screenshot.type, screenshot.quality, screenshot.omitBackground |
| Freeze animations | animations: 'disabled' | animations |
| PDF in a paper size | page.pdf({ format: 'A4' }) | pdf.format |
| PDF margins, scale, pages, orientation | margin, scale, pageRanges, landscape | pdf.margin, pdf.scale, pdf.pageRanges, pdf.landscape |
| Screen or print CSS, dark mode | page.emulateMedia({ media, colorScheme }) | mediaType, colorScheme |
| Emulate a phone | newContext(devices['iPhone 15 Pro']) | device: 'iPhone 15 Pro' |
| Custom viewport | page.setViewportSize() | viewport |
| Wait for an element | page.waitForSelector() | waitForSelector |
| Wait for a load event | page.goto(url, { waitUntil }) | waitUntil |
| Wait a fixed time | page.waitForTimeout() | waitForTimeout |
| Send cookies or auth headers | page.setExtraHTTPHeaders() | headers |
| Block ads, trackers, cookie banners | page.route() + route.abort() | adblock (on by default) |
| Click, then scroll to a section | locator.click(), scrollIntoViewIfNeeded() | click, scroll |
| Inject CSS or JavaScript | page.addStyleTag(), page.addScriptTag() | styles, scripts, modules |
| Render without JavaScript | newContext({ javaScriptEnabled: false }) | javascript: false |
| Route through a proxy | launch({ proxy }) | proxy, proxy.location |
| Cap the time spent | page.setDefaultTimeout() | timeout |
| Run custom code on the page | page.evaluate() | function |
Playwright names come from the Page API reference, which marks
page.waitForSelector and page.waitForTimeout as discouraged in tests. Defaults differ: Playwright prints PDFs on Letter, Microlink on A4, and Microlink disables animations unless asked. headers and proxy are Pro parameters. waitUntil takes networkidle0 or networkidle2 where Playwright takes networkidle. The function parameter receives a Puppeteer page, not a Playwright one.No browser to run The same request, every time
2.8
secs
P95 screenshot
1.6
secs
P95 PDF
99.9
%
SLA Guaranteed
Start free, scale when ready
One price per 1,000 requests on every tier, with the browser, the proxy and the cache included. Spend the quota on screenshots, PDFs or scraping in whatever mix the month needs, and stop sizing workers for the busiest hour.
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
Capability by capability, side by side.
Both drive a real browser. Playwright is a library and test runner you host; Microlink is an API that hosts the browser and returns the result. Every Playwright row comes from playwright.dev or the Playwright repository, including the rows where Playwright is the better choice.
| Capability | Microlink | Playwright |
|---|---|---|
| Infrastructure to run Playwright needs browser binaries matched to its version, and the official Docker image must match the Playwright version in the project. | None, one HTTPS call | Browsers, image, workers |
| Billing unit Microlink is $1.07 per 1,000 requests on every self-serve Pro plan, from $49 for 46,000 to $450 for 420,000. Playwright is free and open source; the cost is the compute, memory and time to keep it running. | 1 request | Your servers |
| Screenshot Both capture the viewport, the full page or a single element. Microlink returns a CDN URL instead of a buffer. | ✓ | ✓ |
| PDF In the Playwright source, only the Chromium page implements page.pdf. Microlink renders every PDF in Chrome. | ✓ | Chromium only |
| Response caching ttl sets how long Microlink keeps a result at the edge. With Playwright, storing and reusing a capture is your code. | 1 minute to 31 days | Your code |
| Proxy for blocked targets Microlink resolves a proxy automatically on Pro and proxy.location pins the exit country. Playwright accepts a proxy server at launch. | Managed on Pro | Bring your own |
| Antibot reporting Microlink names the antibot or CAPTCHA provider that blocked a request. | ✓ | Your code |
| Ad and tracker blocking | On by default | Write route rules |
| Page metadata and markdown Microlink returns title, description, author, date, logo and markdown in the same response as the screenshot. Playwright can extract all of it too, with selectors and parsing code you maintain per site. | ✓ | Code you write |
| Requests in parallel On a paid Microlink plan, parallelism is capped only by the requests left in the month. A free key handles 2 in flight. With Playwright, the ceiling is the browsers your machines can hold. | Unthrottled on Pro | As many as you host |
| Custom code on the page Microlink Function hands your code a Puppeteer page, so Playwright code moves only after a rewrite: locators, auto-waiting and web-first assertions stay behind. | Puppeteer API | Playwright API |
| MCP server for agents Playwright MCP drives a browser through accessibility snapshots. Microlink MCP returns screenshots, PDFs, markdown and metadata per URL. | ✓ | ✓ |
| Firefox and WebKit Playwright drives Chromium, Firefox and WebKit with one API. Microlink runs Chrome only. | ✕ | ✓ |
| Test runner and assertions Playwright Test runs tests in parallel with browser isolation, auto-waiting and web-first assertions. | ✕ | ✓ |
| Tracing and Trace Viewer | ✕ | ✓ |
| Codegen test recorder | ✕ | ✓ |
| Works offline and on localhost Microlink fetches public URLs from its own network, so a dev server on localhost is out of reach. | ✕ | ✓ |
| Free tier Signing up for a Microlink key, with no card, gives 25 requests per day; without a key, 5 per day still go through. Playwright ships under Apache-2.0; the hosting bill is yours. | 25/day | Open source |
Last verified: November 2026. Check each product’s docs for the latest.
Where Playwright is the better tool.
Microlink replaces the screenshot, PDF and scraping service. For testing your own app, keep Playwright.
Testing your own app
Playwright Test brings the runner, fixtures, browser isolation, auto-waiting and web-first assertions. Microlink has no test runner and does not try to be one.Firefox and WebKit
Playwright drives Chromium, Firefox and WebKit with one API, so a Safari rendering bug shows up before release. Microlink runs Chrome only.Debugging what happened
The Trace Viewer records every action, DOM snapshot, network request and console message, and Codegen writes a test while you click. Microlink returns the result and the response headers.Local, private and offline
Playwright runs against localhost, behind a VPN or with no network at all, and costs nothing per run. Microlink fetches every URL from its own network and rejects private and internal addresses with EFORBIDDENURL, so an intranet page stays out of reach.Answers in milliseconds
Microlink starts an isolated browser for each request, so a capture takes seconds, as the P95 figures above show. A Playwright context kept open next to your app reuses a running browser and returns far sooner. When a user waits on the result, a warm pool you host wins.Millions of captures on a flat curve
At $1.07 per 1,000 requests, the API bill grows with every capture. A machine you already own and keep busy around the clock can undercut that per screenshot, as long as the hours spent on browser upgrades, crashes and Docker pins go on the same ledger.
Product Information
What moves, what stays in Playwright, and what happens to the worker running page.screenshot today.
Should I replace Playwright in my test suite?
No. For end-to-end testing Playwright is the right tool: it runs Chromium, Firefox and WebKit, isolates every test, waits automatically and ships assertions, tracing and Codegen. Microlink replaces the other job Playwright often ends up doing, a production service that takes screenshots, prints PDFs or scrapes pages on demand.
Can I run my Playwright script on Microlink?
Not as is. Most screenshot and PDF scripts become query parameters:
fullPage, format, device, waitForSelector, headers and the rest map one to one. For custom steps, the function parameter runs your JavaScript with a Puppeteer page, not a Playwright one, so locators and expect calls need rewriting as Puppeteer calls.Does Microlink support Firefox or WebKit?
No. Microlink runs Chrome for every request, because one engine has to produce the screenshot, the PDF and the DOM consistently. The reasons are in Why we still run Chrome. If you need to see how a page renders in Safari or Firefox, run Playwright for that check.
How do PDFs compare with page.pdf?
Both print through Chromium. Playwright implements
page.pdf on Chromium only, so a Firefox or WebKit page cannot print. Microlink takes the same options as pdf parameters (format, margin, scale, pageRanges, landscape) and defaults to A4 where Playwright defaults to Letter. The PDF comes back as a CDN URL instead of a buffer.What does it cost compared with hosting Playwright?
Pro starts at $49 for 46,000 requests a month and tops out self-serve at $450 for 420,000, the same $1.07 per 1,000 at every step, with the browser, proxy resolution and edge cache included. Playwright costs nothing to download; what you pay for is the machines, the memory each browser holds, the proxies, and the engineering time spent keeping browser builds and the Docker tag in step.
What are the rate limits?
Paid plans apply no throttling: run as many parallel requests as the monthly quota allows. The free API key runs 2 requests at a time against 25 requests a day, and 5 a day work with no key at all.
Does Microlink have an MCP server like Playwright MCP?
Yes, with a different job. Playwright MCP lets an agent drive a browser step by step through accessibility snapshots. The Microlink MCP server gives an agent one tool call per URL that returns a screenshot, a PDF, markdown or metadata, with no browser session to manage.
Start building
Take the URL your Playwright worker screenshotted last and send it as one request.
Get your free API key25 requests/day · Every Pro feature · No credit card
Playwright and Microsoft are trademarks of their respective owners. Microlink is not affiliated with or endorsed by them. Competitor details come from their public pages and may have changed since they were checked.