url2png launched around 2010 and became one of the first dedicated screenshot APIs. It still works — you construct a signed URL, hit the endpoint, get back a PNG. For teams already integrated with url2png, that simplicity has kept them on the platform for years. But web rendering has changed beyond recognition since 2010, and developers searching for a url2png alternative usually run into the same set of friction points: PNG-only output, MD5 request signing, no built-in content blocking. I built screenshotrun, so factor that bias in. Everything below is checkable against both products' documentation.
This comparison walks through the technical differences, pricing math, authentication models, output formats — plus the scenarios where url2png is still a perfectly reasonable choice.
Two APIs from different eras
url2png was an early mover. Back when taking a website screenshot meant spinning up a PhantomJS process on your own server, having someone else handle the browser was a genuine improvement. The API design reflects that era: you append parameters to a URL, sign the whole thing with an MD5 hash of your API secret. The endpoint returns a PNG image. Simple, predictable, cacheable via their Fastly CDN.
screenshotrun was built after Chromium became the de facto rendering engine and after headless Chrome replaced PhantomJS entirely. The API assumes you want control over output format, device emulation, content blocking, wait strategies — things that barely existed as concepts when url2png shipped its first version. Authentication is a Bearer token in the header, which is the pattern most developers already use for every other API in their stack.
Neither approach is wrong. But the gap between a 2010-era GET-with-MD5-signature API and a modern REST endpoint with Bearer auth shows up in every integration you build on top of it.
Feature comparison
| Category | screenshotrun | url2png |
|---|---|---|
| Authentication | Bearer token in header | API key + MD5 request signing |
| Output formats | PNG, JPEG, WebP, AVIF, TIFF, PDF | PNG only |
| Free tier | 200/mo, permanent, no card | None |
| Starting price | $9/mo for 3,000 screenshots | $29/mo for 5,000 screenshots |
| Full-page capture | Yes, auto-scroll with lazy image loading | Yes (viewport up to 5000px height) |
| Viewport control | Custom width/height + device presets | Custom viewport up to 5000x5000 |
| HTML/Markdown input | Yes | No (URL only) |
| Dark mode | Yes | No |
| Retina / 2x | Yes, all plans | No |
| Stealth mode | Yes, all plans | No |
| Ad blocking | Yes, toggle per request | No |
| Cookie banner blocking | Yes, toggle per request | No |
| Chat widget blocking | Yes, toggle per request | No |
| CSS/JS injection | Yes, all plans | Custom CSS only |
| Wait-for-selector | Yes, configurable timeout | say_cheese flag (waits for element) |
| Delay before capture | Yes (milliseconds) | Yes (seconds) |
| Custom headers | Yes (arbitrary headers) | Accept-Language, User-Agent only |
| Geolocation | Yes, configurable | No |
| Certified screenshot | Yes (cryptographic proof) | No |
| Webhook delivery | Yes | No |
| MCP server | Yes, first-party | No |
| Scroll video | Yes (auto-scroll recording) | No |
| CDN caching | Configurable TTL | 30-day Fastly CDN cache |
| Concurrent workers | No artificial limit | 10-35 depending on plan |
url2png covers the basics well — viewport control, full-page capture, CSS injection, delay. Where it drops off is everything that came after 2015: content blocking, device emulation beyond viewport sizing, retina rendering, format flexibility. screenshotrun includes all of those on every plan, including the free tier.
MD5 signing vs Bearer token
This is the difference developers notice first. url2png authenticates requests by hashing the query string with your API secret using MD5. You concatenate your secret key with the query parameters, compute the hash, append it to the URL. Every language needs a slightly different implementation — you can't just pass a header and move on.
A url2png request in practice (pseudocode):
# url2png authentication
query = "url=https://example.com&viewport=1280x800"
token = md5(secret_key + query)
request_url = f"https://api.url2png.com/v6/{api_key}/{token}/png/?{query}"
And the same capture with screenshotrun:
curl "https://api.screenshotrun.com/v1/screenshots/capture?url=https://example.com&width=1280" \
-H "Authorization: Bearer YOUR_API_KEY"
Bearer token authentication works the same way across every HTTP client, every language, every framework. No hashing step, no string concatenation, no risk of encoding mismatches breaking your signature. (I've seen url2png forum posts from developers debugging MD5 signature failures caused by URL-encoding differences between languages — that entire category of bug disappears with Bearer auth.)
MD5 signing also means your url2png requests are GET-only with all parameters in the URL. That limits how much data you can pass. screenshotrun accepts the same parameters via GET query strings or POST body, so things like custom CSS injection or long lists of selectors don't bump into URL length limits.
Pricing side by side
| Scenario | screenshotrun cost | url2png cost |
|---|---|---|
| Testing / prototyping | Free (200/mo, no expiry) | $29/mo minimum |
| Low volume (2,000/mo) | $9/mo | $29/mo |
| Medium volume (5,000/mo) | $9/mo (3,000 included + overage) or $29/mo | $29/mo |
| High volume (20,000/mo) | $29/mo (15,000) + overage or $49/mo | $99/mo |
| 50,000/mo | $99/mo | $199/mo |
The gap starts at the bottom. url2png has no free tier at all — $29/mo is the floor. For a developer who wants to test an integration before committing budget, that's a hard sell. screenshotrun's free tier (200 screenshots/month, no credit card, no time limit) covers prototyping and low-traffic production use cases without any spending approval required.
At scale the difference stays consistent. url2png's $199/mo plan gives you 50,000 screenshots with 35 concurrent workers. screenshotrun's $99/mo plan covers the same volume without artificial concurrency limits. (url2png also charges overage fees: $0.004 to $0.006 per additional screenshot depending on your plan. screenshotrun charges overages too, but the per-screenshot rate is lower because the base plans include more volume per dollar.)
One pricing advantage url2png has: their plans include a set number of concurrent workers, which gives you predictable parallelism. If you need to fire off 35 screenshots simultaneously and know they'll all process in parallel, that worker count is a clear commitment. screenshotrun doesn't publish a fixed worker number — requests are processed as they come in without a hard concurrency cap on paid plans.
The PNG-only limitation
url2png returns PNG. That's the only output format. The name of the product is literally "url to PNG." When the service launched, PNG was the obvious choice — lossless, widely supported, simple. For many use cases it's still fine.
Where it becomes a problem: file size. A full-page screenshot of a content-heavy site easily reaches 3-5 MB as PNG. The same capture as WebP comes in around 800 KB. AVIF drops it even lower. If you're storing thousands of screenshots or serving them to end users through a web app, that 4x file size difference hits your storage costs and your page load times.
screenshotrun supports six output formats (PNG, JPEG, WebP, AVIF, TIFF, PDF) — all from the same endpoint, controlled by a single format parameter. No post-processing, no format conversion pipeline on your side. Swap format=png to format=webp and the response changes. That also means you can generate PDFs directly from any URL, which url2png can't do at all.
# WebP output — same endpoint, different format
GET https://api.screenshotrun.com/v1/screenshots/capture?url=https://example.com&format=webp&quality=85
Authorization: Bearer YOUR_API_KEY
If your workflow genuinely only needs PNG, this isn't a reason to switch. But if you've ever had to bolt on ImageMagick or Sharp to convert url2png output into a web-friendly format, you already know the pain.
Content blocking — the missing layer
Modern websites come loaded with overlays. Consent dialogs, promotional popups, chat widgets, ad placements — all of them end up in your screenshot unless you deal with them. url2png has no built-in mechanism for any of this. Your options are limited to CSS injection (hiding elements by selector) on their docs, which means you need to know the exact selectors for each site's overlays. Those selectors change every time the site updates its layout.
screenshotrun takes a different approach. Three boolean parameters handle the most common overlays:
GET https://api.screenshotrun.com/v1/screenshots/capture?url=https://example.com&block_ads=true&block_cookies=true&block_chats=true
Authorization: Bearer YOUR_API_KEY
block_ads uses filter lists (similar to what browser ad blockers use) to strip advertising before the page renders. block_cookies intercepts consent dialogs — GDPR banners, CCPA notices, the various cookie walls that cover half the viewport on European sites. block_chats removes Intercom, Drift, Zendesk, LiveChat, plus similar support widgets. All three work without you knowing anything about the target page's DOM structure.
For pages where the default blocking misses something, hide_selectors lets you pass custom CSS selectors to remove specific elements. That's similar to url2png's CSS injection, but layered on top of the automated blocking rather than being your only option.
When url2png still makes sense
url2png isn't a bad product. It's a focused one. There are situations where it's the right call, even compared to a newer API.
If your integration already works and you don't need features beyond PNG capture — keep it. Migration for the sake of migration wastes engineering time. url2png's CDN-backed delivery through Fastly is genuinely fast. The 30-day cache means repeated requests for the same URL return instantly without burning a new capture. That caching model works well for thumbnail generation, link previews, or any use case where freshness isn't critical.
The say_cheese parameter is a clever approach to timing. Instead of guessing a delay value, you embed a JavaScript snippet in the target page that signals "ready." url2png waits for that signal before capturing. If you control the target page and can add that snippet, it's more reliable than a fixed delay. (screenshotrun uses wait_for_selector for a similar purpose, waiting for a specific DOM element to appear — but that doesn't require modifying the target page.)
url2png's viewport goes up to 5000x5000 pixels. That's generous for specialized use cases like capturing large data visualizations or wide dashboards that don't fit standard viewport dimensions.
Where developers hit friction with url2png
The pain points I see mentioned repeatedly across forums and comparison sites fall into predictable categories.
Rendering quality on modern sites. url2png's rendering engine reportedly struggles with newer CSS features — Flexbox layouts, CSS Grid, WebGL content. Full-page screenshots sometimes show repeating scrollbars or horizontal seams where viewport segments were stitched together. These are rendering engine issues that reflect the age of the underlying browser technology.
No retina support. url2png captures at 1x device pixel ratio only. No documented way exists to get 2x resolution output. If you're generating screenshots for retina displays (which is most modern screens at this point), the images look soft. screenshotrun's retina=true parameter doubles the device pixel ratio, producing crisp output for high-density displays.
No JavaScript injection. url2png supports custom CSS but not custom JavaScript. You can hide elements, change colors, override fonts — but you can't execute code before the capture. Dismissing a modal by clicking a button, scrolling to a specific section, expanding a collapsed accordion — CSS can't do any of that. screenshotrun's js parameter lets you inject arbitrary JavaScript that runs before the screenshot, and click_selector handles the click-before-capture pattern without writing any JS at all.
The worker concurrency model. url2png's plans include 10 to 35 workers. If you fire more simultaneous requests than your plan allows, the excess requests queue. For bursty workloads (your app suddenly needs 100 screenshots in 30 seconds), that queue can introduce significant latency. Upgrading your plan for burst capacity means paying the higher rate all month for what might be a once-a-week spike.
Migrating from url2png
The migration is mostly mechanical. url2png and screenshotrun are both HTTP APIs that accept a URL and return an image — the request format changes, but the integration pattern stays the same.
Start with the authentication. Remove the MD5 signing logic, add a Bearer token header. This is the biggest code change because the signing code is probably scattered across your codebase or wrapped in a helper function.
Next, map your parameters. Most have direct equivalents:
# url2png parameters → screenshotrun equivalents
viewport=1280x800 → width=1280&height=800
fullpage=true → full_page=true
delay=3 → delay=3000 (milliseconds, not seconds)
say_cheese=true → wait_for_selector=.your-element
custom_css_url=... → css=... (inline CSS, no external URL needed)
accept_languages=en-US → headers={"Accept-Language":"en-US"}
user_agent=... → user_agent=...
Response handling needs a small update too. url2png returns the image directly (or a CDN URL to a cached image). screenshotrun also returns the image directly by default. If you were relying on url2png's 30-day CDN cache, set cache_ttl to get similar behavior — though you can also set it to a shorter interval if you need fresher captures.
After the basics work, take advantage of what's new. Once the basic migration works, you can add format=webp to cut file sizes, block_ads=true to clean up captures, retina=true for sharp output on modern displays. None of these require architectural changes — they're just extra query parameters on the same request.
Start with the free tier. 200 screenshots per month, no credit card. Run your existing integration against both APIs in parallel, compare the output, switch over when you're satisfied. The whole migration usually takes less than a day for a typical integration.
Choosing between the two
url2png is a stable, minimal screenshot API that does one thing: convert a URL into a PNG image. It's been doing that since 2010. If PNG is all you need and your integration already works without content blocking or retina or format flexibility — moving would be migration for its own sake.
If you're starting fresh, or you've been hitting the edges of what url2png offers, screenshotrun gives you the controls that a 2010-era API couldn't have anticipated. Six output formats instead of one. Automated content blocking. Stealth mode for bot-protected sites. Retina rendering. Webhook delivery. PDF generation from any URL. Every feature available on every plan, including the free tier.
The screenshot API comparison covers additional alternatives if neither product fits your requirements. And the integration guides show code samples for connecting screenshotrun with your language or platform — from Python to Node.js to Go and beyond.
FAQ#
url2png has been operating since approximately 2010 and remains functional. Their API continues to serve requests through the Fastly CDN. However, the feature set has not expanded significantly in recent years — the API still outputs PNG only, uses MD5 request signing, and lacks features like content blocking or retina rendering that newer screenshot APIs include.
No. url2png does not offer a free tier. Their lowest plan starts at $29/month for 5,000 screenshots. screenshotrun offers a permanent free tier with 200 screenshots per month, no credit card required, which covers prototyping and low-volume production use cases.
No. url2png outputs PNG images exclusively — the name of the product reflects this. If you need WebP, JPEG, AVIF, or PDF output, you would need to convert the PNG after receiving it or use a different screenshot API. screenshotrun supports all six formats from the same endpoint via the format parameter.
url2png uses API key plus MD5 request signing — you hash your secret key with the query string and include the hash in the URL. screenshotrun uses Bearer token authentication in the HTTP header, which is the standard pattern for modern REST APIs. Bearer auth is simpler to implement and avoids the encoding-related signature bugs that MD5 signing can produce.
For a typical integration, the migration takes less than a day. The main changes are replacing the MD5 signing logic with a Bearer token header and mapping url2png parameters to screenshotrun equivalents (most have direct counterparts). You can run both APIs in parallel during the transition using screenshotrun free tier.