Serve high-volume screenshots through traffic spikes
High-volume screenshots rarely arrive at a steady rate. A product launch, a viral post or a Monday morning batch job multiplies demand in minutes, and a self-hosted browser pool has to be sized, and paid for, at that peak. The Screenshot API applies no throttling, serves repeats from a cache whose hits do not count against your quota, and spends your plan only on fresh captures.
Screenshot traffic spikes are when self-hosted browsers fail
Headless Chrome is memory hungry and slow to start. A pool sized for average load queues or times out when ten times the traffic arrives, so captures fail exactly when the most people are looking. A pool sized for the peak sits idle, and billed, for the rest of the month.
The usual workarounds move the problem instead of removing it. A job queue protects the browsers but turns a burst into minutes of latency. Adding containers on demand helps only if new browsers boot faster than the spike grows, and a rate limiter in front of everything drops the requests you cared about.
Microlink applies no throttling limitation: you can run as many parallel requests as your quota allows. Every response is cached for 24 hours by default, a repeat of the same request is a cache hit that does not count against your quota, and each fresh capture runs in its own isolated browser. Every paid plan adds a 99.9% uptime SLA, so a burst hits the cache first and a managed browser fleet second.
How to serve high-volume screenshots during a spike
Three request options turn a spiky workload into a predictable one, and none of them needs infrastructure on your side. The screenshot caching and performance guide covers the same setup in more depth.
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const { url } = await microlink.screenshot('https://example.com', {
ttl: '1d',
staleTtl: 0
})ttl keeps the capture for a day, and staleTtl at 0 serves the cached copy instantly while a fresh one is generated in the background. The result is the usual asset object with url, width, height and size.
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const targets = ['https://a.com', 'https://b.com', 'https://c.com']
const screenshots = await Promise.all(
targets.map(target => microlink.screenshot(target, { retry: 3 }))
)No per-second limiter sits in front of the API, so Promise.all over a list of targets is fine and only your quota bounds it. retry raises the server-side retries with exponential backoff from the default of 2 to 3.
curl 'https://pro.microlink.io/?url=https%3A%2F%2Fexample.com&screenshot=true&meta=false&ttl=1d&staleTtl=0' \
-H 'x-api-key: $MICROLINK_API_KEY'ttl and staleTtl need a Pro key, so the URL targets pro.microlink.io and carries the x-api-key header. Read x-cache-status in the response: MISS on the first call, HIT on every repeat.
- ttl Cache lifetime from 1 minute to 31 days, including the min and max aliases. Pro plans; the default is 24 hours everywhere.
- staleTtl Serves the cached response immediately while revalidating in the background. Cannot exceed ttl. Pro plans.
- retry Server-side retries with exponential backoff on unexpected browser errors. Default 2.
- meta false skips metadata extraction, usually the biggest single speedup for screenshot-only requests.
- cacheKey Appends a custom identifier to the cache key to keep separate entries per tenant or variant. Pro plans.
Log x-cache-status, x-response-time and x-rate-limit-remaining from the response headers to see how much of a burst the cache absorbed and how much quota is left. The production patterns guide lists every header worth watching.
Why a managed API survives screenshot traffic spikes
Bursty traffic is a capacity problem, and capacity is exactly what a managed browser service pools across every customer. Three properties do the work.
When the quota runs out you get HTTP 429 with the ERATE error code, plus x-rate-limit-remaining and x-rate-limit-reset headers, so back-pressure is explicit instead of a silent slowdown.
staleTtl at 0 is the caching default worth copying: visitors always get an instant response while the copy refreshes behind them. The same pattern keeps dynamic Open Graph images fast when a link goes viral.
When not to: a steady trickle of a few captures per day fits the free tier of 25 requests per day, and a one-off batch of up to 25 URLs is quicker with the bulk screenshot tool. The API pays off when demand moves faster than you can provision.
FAQ
Does the screenshot API rate limit requests per second?
What happens when a screenshot spike exceeds my quota?
Do cached screenshots count against my quota?
How do I keep high-volume screenshots fresh without re-rendering on every hit?
Can I get dedicated capacity for screenshot workloads?
Solve the next problem with the same API
Faster, smaller screenshots
Dynamic Open Graph images
Screenshot blocked websites
PDFs in bulk
Bulk Markdown conversion with caching
Link previews at scale
Ready for unpredictable traffic?
No browsers to size, no queues to babysit. Start on the free tier with 25 requests per day, then pick a paid plan matched to your monthly volume.