Microlink and Urlbox both take a URL and give you back a screenshot, but they come from different directions.
- Microlink started as a link-preview and metadata API. A screenshot is one of many things one GET request can return, alongside title, description, logo and more. Responses are JSON with a hosted image URL, and the service caches aggressively.
- Urlbox is a capture-first rendering API. It has a long list of render options (cookie banners, ad blocking, full page, selectors, PDF, video, Markdown), returns a render URL from a POST, and bills per render.
Choose Microlink when you want previews and metadata for many URLs and repeat requests should be cheap. Choose Urlbox when the capture itself must be right on hard third-party sites and you will pay for that.
Disclosure: I build RenderScreenshot, which competes with both. We timed Microlink's free keyless endpoint ourselves. We have no Urlbox account, so we have no Urlbox timings; its column comes from its docs and pricing page, checked on 2026-10-15.
Our comparison hub has more pairs. For a ranked list that includes both, see the screenshot API comparison.
Verdict
| You need... | Microlink | Urlbox |
|---|---|---|
| Title, description, image and logo in the same call | Yes, by default | Metadata is a render option, not the main product |
| Start without a credit card | Free keyless endpoint and a free plan | 7-day trial, no card; no free plan |
| Cheap repeat requests for the same URL | Built-in cache with ttl and force |
Sync REST endpoint is not cached |
| Hide cookie banners, click "accept", block ads | Check the option list for your case | hide_cookie_banners, click_accept, block_ads |
| PDF, video (MP4/WebM), Markdown output | PDF and Markdown are separate Microlink products | All from the same endpoint via format |
Links you can put in an <img> |
embed=screenshot.url returns the image itself |
Render links that carry a token |
| Save renders to your own S3 bucket | Not covered here | Hi-Fi plan and above (any S3-compatible store on Ultra and above) |
What we measured on Microlink's free endpoint
Method: 2026-10-15, Node 22.18.0 on our development machine, the keyless https://api.microlink.io/ endpoint with screenshot=true&meta=false. Two targets. To force a fresh render we added a unique query string to each URL, then repeated the identical request twice. "API time" is until the JSON arrived; "download" is fetching the image from the URL in that JSON.
| Target | Request | API time | Download | Image |
|---|---|---|---|---|
| example.com | First (new URL) | 1,258 ms | 272 ms | PNG, 2560x1600, 169 KB |
| example.com | Repeat 1 / 2 | 52 / 44 ms | 52 / 144 ms | Same file |
| wikipedia.org | First (new URL) | 2,707 ms | 143 ms | PNG, 2560x1600, 465 KB |
| wikipedia.org | Repeat 1 / 2 | 39 / 52 ms | 59 / 128 ms | Same file |
Three things stood out:
- The default image is 2x. A plain request returned 2560x1600 pixels. That is sharp on retina screens, but it is about four times the pixels of a 1x capture. For thumbnails, ask for a 1x device scale or resize on your side.
- Repeats are served from cache in about 40 to 50 ms. Microlink documents a two-level cache: its own store plus Cloudflare edge nodes. The
x-rate-limit-remainingheader did not go down for our repeat requests; it went down once per new URL. - One sample is not a benchmark. This is two URLs, one location and no Urlbox column. The script below runs the same test with your URLs and both vendors.
Response shape and auth
The two APIs return different things, and that shapes your code more than any option does.
| Microlink | Urlbox | |
|---|---|---|
| Request | GET /?url=...&screenshot=true |
POST /v1/render/sync with JSON options |
| Auth | None (free) or x-api-key header on pro.microlink.io |
Authorization: Bearer <secret> |
| Response | JSON: data.screenshot.url, width, height, type, size |
JSON: renderUrl, size |
| Image in the response body | Add embed=screenshot.url |
Use a render link instead of the REST call |
| Hosted file lifetime | Governed by the cache ttl |
renderUrl expires after 30 days |
| Long renders | Not covered here | After 95 s, a redirect to keep waiting (redirect_after sets the time) |
Microlink: we ran this against the free endpoint on 2026-10-15. It saved a 2560x1600 PNG of 168,630 bytes.
// Microlink: one GET returns JSON with a hosted screenshot URL (plus metadata if you ask). // Without a key this uses the free endpoint; with MICROLINK_API_KEY it uses pro.microlink.io. import { writeFile } from 'node:fs/promises'; const key = process.env.MICROLINK_API_KEY; const api = new URL(key ? 'https://pro.microlink.io/' : 'https://api.microlink.io/'); api.searchParams.set('url', 'https://example.com'); api.searchParams.set('screenshot', 'true'); api.searchParams.set('meta', 'false'); // skip metadata extraction if you only need pixels const res = await fetch(api, { headers: key ? { 'x-api-key': key } : {} }); const body = await res.json(); if (body.status !== 'success') throw new Error(`Microlink ${res.status}: ${JSON.stringify(body)}`); const { url, width, height, type } = body.data.screenshot; const image = Buffer.from(await (await fetch(url)).arrayBuffer()); await writeFile(`example.${type}`, image); console.log(`${width}x${height} ${type}, ${image.length} bytes`);
Urlbox: we ran this against a local mock that checks the bearer header and the required url. It has not run against Urlbox's live API.
// Urlbox: POST render options, get JSON with a temporary render URL. import { writeFile } from 'node:fs/promises'; const secret = process.env.URLBOX_SECRET; if (!secret) throw new Error('Set URLBOX_SECRET'); const res = await fetch('https://api.urlbox.com/v1/render/sync', { method: 'POST', headers: { Authorization: `Bearer ${secret}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ url: 'https://example.com', format: 'png', width: 1280, height: 800, hide_cookie_banners: true, }), }); if (!res.ok) throw new Error(`Urlbox ${res.status}: ${await res.text()}`); const { renderUrl, size } = await res.json(); await writeFile('example-urlbox.png', Buffer.from(await (await fetch(renderUrl)).arrayBuffer())); console.log('saved', size, 'bytes from', renderUrl);
Both return a link, not the image, so both cost a second request to get the bytes. If you serve the image to browsers, you can hand them the link and skip that download.
How billing differs
The prices below are from each pricing page on 2026-10-15. Microlink lists prices in euros.
| Requests per month | Microlink | Urlbox |
|---|---|---|
| 1,000 | €39 (smallest paid plan, 46,000 requests); the free plan covers 100 | $19 Lo-Fi (2,000 renders, "websites you own") or $49 Hi-Fi (5,000) |
| 10,000 | €39 (46,000 requests) | $99 Ultra (15,000 renders) |
| 100,000 | €120 (140,000 requests) | Business: $495 base, then $3 per 1,000 renders |
The headline numbers hide the rules that decide your bill:
- Urlbox counts renders, not requests. Its pricing page says a request uses one render per 30 seconds of render time and one per 5 MB of output. GPU rendering doubles the count, and managed proxies multiply it (from 2x up to 50x). Hard sites cost more than easy ones.
- Urlbox's sync endpoint does not de-duplicate. The same request twice is two renders. Cache on your side, or use render links.
- Microlink's quota is per request, and cache hits looked free in our test. For link previews, where many users ask for the same popular URLs, that matters more than the per-request price.
- Urlbox's cheapest plan is for sites you own. Its pricing page describes Lo-Fi as low-quality captures for third-party websites. For captures of other people's sites, budget for Hi-Fi or above.
Benchmark both on your own URLs
Use 20 to 30 URLs that look like your traffic, three runs each, and count a run as a success only if the image downloads and is not blank. The checklist for choosing a screenshot API has a scoring sheet. A minimal loop around the two snippets above is enough:
- Put your URLs in a text file, one per line.
- For each URL, call Microlink, then Urlbox. Record the API time, download time, image size and dimensions.
- Repeat the whole list twice more. Keep the first pass separate: it shows cold behaviour, and the later passes show cache behaviour.
- Open every image. Score cookie banners, missing images and wrong fonts by hand.
Mind Microlink's keyless allowance during step 3. After our run the x-rate-limit-remaining header showed 7 requests left for the day, so use a free key for a real test.
When each one wins
Microlink wins for link previews, unfurls and directories: you want metadata plus a picture for many URLs, many of them repeated, at a low per-request price. Its free endpoint also makes it the fastest way to try a screenshot in a prototype.
Urlbox wins when capture quality on hard pages is the product: archives, compliance captures, visual monitoring of third-party sites. Its option list for cookie banners, ads, proxies and long renders is deep, and it can write to your own S3 bucket.
How RenderScreenshot compares on these points
RenderScreenshot returns the image bytes from /v1/screenshot and puts a public CDN link in the X-Cache-URL response header, so you get the file and a shareable link from one request. A GET with flat query parameters works like Microlink's single GET. Renders are cached by default for 24 hours (configurable), and X-Cache-Hit tells you whether a response came from cache. See response headers. Page metadata extraction is planned but not live yet, so for titles, descriptions and logos today, Microlink is the better tool.
// RenderScreenshot: the same capture as a GET with flat query parameters. // The body is the image; the X-Cache-URL header is a public CDN link to the same file. import { writeFile } from 'node:fs/promises'; const api = new URL('https://api.renderscreenshot.com/v1/screenshot'); api.search = new URLSearchParams({ url: 'https://example.com', width: '1280', height: '800', format: 'webp' }); const res = await fetch(api, { headers: { Authorization: `Bearer ${process.env.RS_API_KEY}` } }); if (!res.ok) throw new Error(`RenderScreenshot ${res.status}: ${await res.text()}`); await writeFile('example.webp', Buffer.from(await res.arrayBuffer())); console.log('cache hit:', res.headers.get('x-cache-hit'), 'CDN copy:', res.headers.get('x-cache-url'));
We tested this against a local mock of our API, not the live service. We do not offer video capture, and proxy routing is still on our roadmap, so Urlbox stays ahead for hard third-party captures. Get a free API key and run your URL list through all three.
Last checked 2026-10-15: Microlink and Urlbox docs and pricing pages. Microlink timings from its keyless endpoint with Node 22.18.0. Urlbox code run against a local mock only.