ScreenshotAPI

Free Screenshot URL (No API Key)

A keyless screenshot endpoint — GET /api/v1/public/screenshot?url=... returns a PNG, JPEG, or WebP image with no API key and no signup. Rate limits, parameters, caps, and embed examples.

You can capture a website screenshot from ScreenshotAPI without an API key and without signing up. Request this URL and you get image bytes back:

https://screenshotapi.to/api/v1/public/screenshot?url=https://example.com

That is a complete, working request. It responds with Content-Type: image/png and the raw image, so it can be dropped straight into an <img src>, a Markdown image, or any HTTP client. Access-Control-Allow-Origin is *, so it also works from browser JavaScript.

This is the keyless tier. It is rate limited to 8 requests per minute per IP, capped at 1920×2000, and does not support PDF output. It is built for demos, prototypes, personal projects, and low-volume embeds. For production workloads, create a free API key — that raises you to 200 screenshots per month at no cost and unlocks the full Screenshot API (PDF, 10000px height, stealth mode, custom wait strategies, caching, webhooks).

Endpoint

GET  /api/v1/public/screenshot
POST /api/v1/public/html-to-image
GET  /api/v1/public/metadata

No authentication header. No account. These are the same endpoints that power the browser-based free tools.

Quick start

<img
	src="https://screenshotapi.to/api/v1/public/screenshot?url=https://example.com&width=1280&height=800"
	alt="Screenshot of example.com"
	width="1280"
	height="800"
/>
![Screenshot of example.com](https://screenshotapi.to/api/v1/public/screenshot?url=https://example.com)
curl "https://screenshotapi.to/api/v1/public/screenshot?url=https%3A%2F%2Fexample.com&width=1280&height=800&format=png" \
  --output screenshot.png
const params = new URLSearchParams({
	url: 'https://example.com',
	width: '1280',
	height: '800',
	format: 'webp'
})

const res = await fetch(
	`https://screenshotapi.to/api/v1/public/screenshot?${params}`
)

if (res.status === 429) {
	// The keyless tier is rate limited. The body tells you where to get a key.
	const { message, signupUrl } = await res.json()
	throw new Error(`${message} (${signupUrl})`)
}

const blob = await res.blob()

Always URL-encode the url value when you build the request programmatically. In hand-written HTML a plain https://example.com works because the browser encodes it, but an unencoded target that itself contains & or ? will be truncated.

Query parameters

GET /api/v1/public/screenshot

Required

ParameterTypeDescription
urlstringThe page to capture. https:// is added if you omit the scheme. Private, reserved, and cloud-metadata addresses are rejected.

Optional

ParameterTypeDefaultDescription
formatstringpngpng, jpeg, or webp. pdf is not available on the keyless tier. JPEG and WebP are encoded at quality 85.
fullPagestringfalsetrue captures the entire scrolling page instead of the viewport.
widthnumberViewport width in pixels. Maximum 1920.
heightnumberViewport height in pixels. Maximum 2000 (the authenticated API allows 10000).
deviceScaleFactornumberPixel density multiplier, for Retina-quality output.
devicestringA device preset that sets width, height, and pixel density together. See below. Overrides width, height, and deviceScaleFactor.
darkModestringfalsetrue sends a prefers-color-scheme: dark hint before capturing.
blockAdsstringfalsetrue hides ad slots and trackers.
removeCookieBannersstringfalsetrue dismisses consent and cookie overlays.
removePopupsstringfalsetrue closes newsletter and interstitial popups.
mockupstringFrame the capture in a device mockup: browser, iphone, or macbook.

Boolean parameters are strings in the query: fullPage=true, not fullPage=1.

Device presets

deviceViewportPixel density
desktop1280×800
desktop-hd1920×1080
ipad820×1180
ipad-pro1024×1366
iphone-15-pro393×852
iphone-se375×667
pixel-8412×915
galaxy-s23360×780
curl "https://screenshotapi.to/api/v1/public/screenshot?url=https%3A%2F%2Fexample.com&device=iphone-15-pro&darkMode=true" \
  --output mobile-dark.png

HTML to image

POST /api/v1/public/html-to-image renders a raw HTML string instead of navigating to a URL. Send JSON:

curl -X POST "https://screenshotapi.to/api/v1/public/html-to-image" \
  -H "Content-Type: application/json" \
  -d '{"html":"<h1 style=\"font-family:system-ui\">Hello</h1>","width":1200,"height":630,"format":"png"}' \
  --output card.png
FieldTypeNotes
htmlstringRequired. Maximum 100,000 characters.
formatstringpng, jpeg, or webp.
fullPagebooleanJSON boolean here, not a string.
widthnumberMaximum 1920.
heightnumberMaximum 2000.

Custom CSS and JavaScript injection are not available on the keyless tier. Inline styles inside your html work normally.

URL metadata

GET /api/v1/public/metadata?url=... returns the page's title, description, and Open Graph / Twitter card tags as JSON — useful for building link previews alongside the image. It is rate limited separately at 20 requests per minute per IP.

curl "https://screenshotapi.to/api/v1/public/metadata?url=https%3A%2F%2Fexample.com"

Limits

LimitKeyless tierFree API key
AuthenticationNonex-api-key
Rate limit8 requests/minute per IP200 screenshots/month
Max width19201920
Max height200010000
FormatsPNG, JPEG, WebPPNG, JPEG, WebP, PDF
Full pageYesYes
Custom JS / CSS injectionNoYes
Stealth mode, wait strategies, response caching, webhooksNoYes
Usage dashboard and logsNoYes

The keyless rate limit is a best-effort, per-instance speed bump — not a quota you can rely on. It resets unpredictably and may tighten at any time without notice, and requests are queued behind a small shared concurrency pool. Do not build a production feature on it. A free API key gives you a stable monthly allowance, your own concurrency, and usage visibility, and never changes underneath you.

Responses

A successful request returns the image bytes with Content-Type: image/png, image/jpeg, or image/webp.

Every response also carries:

HeaderMeaning
x-ratelimit-limitRequests allowed in the current window.
x-ratelimit-remainingRequests left in the current window.
x-screenshotapi-docsA link back to this page.
x-cacheHIT if served from the short-lived render cache, MISS if freshly rendered.
x-duration-msServer-side render time.

Errors

Error responses are JSON and include a docsUrl, plus a signupUrl when an API key would lift the limit you hit.

StatusMeaning
400Invalid options (unsupported format, size over the cap) or a blocked target (private, reserved, or metadata address).
429Keyless rate limit reached. Includes retryAfterSeconds and signupUrl.
502The page could not be captured — unreachable, or the site blocks automated browsers.
503The shared keyless render pool is saturated. Retry shortly, or use an API key.
{
	"error": "Rate limit reached",
	"message": "Too many requests. Try again in 41s. This is the keyless free tier — a free API key raises the limit to 200 screenshots/month with no card: https://screenshotapi.to/sign-up",
	"retryAfterSeconds": 41,
	"rateLimited": true,
	"signupUrl": "https://screenshotapi.to/sign-up",
	"docsUrl": "https://screenshotapi.to/docs/api/free-screenshot-url"
}

Caching and embedding

Successful image responses are sent with Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=600, and identical requests within a short window are served from a render cache (x-cache: HIT).

If you embed the URL in a page that gets real traffic, cache or store the image on your side rather than re-requesting it on every page view. A screenshot of a given URL rarely changes minute to minute, and re-rendering it on every visit will run you into the rate limit. For a durable version of this pattern — capture once, store the result, serve it from your own CDN — use an API key and the caching options on the authenticated endpoint.

Measured behaviour

Captured against production on 2026-07-26 by requesting https://example.com at 1280×800:

RequestResult
Cold render, PNG 1280×800HTTP 200, image/png, 19,655 bytes, 1,205 ms server-side
Same request, cachedHTTP 200, x-cache: HIT, 103 ms end-to-end
Full page, WebPHTTP 200, image/webp, 1,149 ms server-side
device=iphone-15-pro&darkMode=trueHTTP 200, PNG 1179×2556 (3× density)
format=pdfHTTP 400 — Format must be png, jpeg, or webp.
width=4000HTTP 400 — width must be between 1 and 1920.
9th request in one minuteHTTP 429 with retryAfterSeconds and signupUrl

Render time depends on the target page; a heavy, script-driven site takes longer than a static one.

When to move to an API key

Get a free API key — 200 screenshots a month, no credit card — as soon as any of these is true:

  • You need more than 8 captures a minute, or predictable throughput.
  • You need PDF output, or a page taller than 2000 pixels.
  • You need custom JavaScript or CSS injection, stealth mode, or a specific wait strategy.
  • You need to see your usage, or be able to debug a failed capture.
  • The screenshot is part of something you ship to users.

Everything on this page maps one-to-one onto the authenticated endpoint. format becomes type, darkMode=true becomes colorScheme=dark, and device presets become explicit width / height / devicePixelRatio values. See the Screenshot API reference for the full parameter set and the authentication guide for how to send your key.

Acceptable use

The keyless endpoints capture public web pages only. Requests to localhost, private networks, reserved ranges, and cloud metadata endpoints are rejected. Do not use them to bypass paywalls, authentication, consent screens, or access controls, and do not run unbounded automated loops against them. See the terms.

On this page