Hosted MCP server · HTTP API

A real browser for your agent, one URL away.

Claude, Cursor and ChatGPT connect with one URL. Your agent sees the page, reads its exact text, clicks and types through it, and is told about the JavaScript errors and failed requests a screenshot alone would hide. The same renderer is a plain HTTP API for screenshots and PDFs of any page.

100 free renders a month Nothing to install No credit card

See what your agent sees

No key, no sign-up. A few renders an hour, straight from this page.

https://example.com
Example screenshot produced by the API
example render

Beside the image, your agent gets:

Title
HTTP status
JavaScript errors
Failed requests

The page’s exact text, fenced as untrusted:


          
Terminal
curl "https://screenshot-api.net/v1/screenshot?url=https://example.com&width=1280" \
  -H "Authorization: Bearer sk_live_..." \
  -o shot.png
For agents

Give your coding agent eyes

A hosted MCP server. Claude, Claude Code, Cursor and ChatGPT connect with one URL and a sign-in — nothing to download, no key to paste.

Terminal
claude mcp add --transport http screenshot-api https://screenshot-api.net/mcp

Then ask it in words. Connect from any client →

“Check the pricing page after my deploy”

It captures at the resolution a vision model actually reads at, crops to a CSS selector when it needs a closer look, and reads characters from the page text rather than guessing them from pixels.

“Open the menu and search for ‘billing’”

Steps run before the capture: click, type, press a key, hover, scroll, wait for an element. The state an agent needs to check is rarely the one a page loads in.

“Why is the dashboard blank?”

Every capture reports the page’s JavaScript errors and its failed or 4xx/5xx requests. A blank screenshot says something is wrong; TypeError and a 500 from /api/session say what.

“How does it look on a phone?”

Render as an iPhone, a Pixel or an iPad — viewport, pixel density, touch and user agent — so it sees the mobile layout, not a desktop page squeezed narrow.

“Did staging change anything?”

The compare tool renders a page against another URL or a stored baseline and returns the changed regions and a diff image. Post it to Slack if you like.

A page cannot steer it

Page text and error messages come back fenced as untrusted content, with a marker the page cannot forge, so a hostile page cannot tell your agent what to do with your credentials.

The API

One endpoint. Any language.

It is a plain HTTP GET that returns image bytes. If your language can make a request, it can take screenshots.

# Full-page WebP at 2x for a retina display
curl -G "https://screenshot-api.net/v1/screenshot" \
  -H "Authorization: Bearer $SCREENSHOT_API_KEY" \
  --data-urlencode "url=https://example.com" \
  -d "full_page=true" -d "format=webp" -d "scale=2" \
  -o example.webp
const params = new URLSearchParams({
  url: "https://example.com",
  width: "1280",
  format: "webp",
  full_page: "true",
});

const res = await fetch(`https://screenshot-api.net/v1/screenshot?${params}`, {
  headers: { Authorization: `Bearer ${process.env.SCREENSHOT_API_KEY}` },
});
if (!res.ok) throw new Error((await res.json()).message);

const buffer = Buffer.from(await res.arrayBuffer());
q := url.Values{}
q.Set("url", "https://example.com")
q.Set("width", "1280")
q.Set("format", "webp")

req, _ := http.NewRequest("GET",
    "https://screenshot-api.net/v1/screenshot?"+q.Encode(), nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("SCREENSHOT_API_KEY"))

res, err := http.DefaultClient.Do(req)
if err != nil {
    return err
}
defer res.Body.Close()

img, err := io.ReadAll(res.Body)
import os, requests

res = requests.get(
    "https://screenshot-api.net/v1/screenshot",
    headers={"Authorization": f"Bearer {os.environ['SCREENSHOT_API_KEY']}"},
    params={
        "url": "https://example.com",
        "width": 1280,
        "format": "webp",
        "full_page": "true",
    },
    timeout=60,
)
res.raise_for_status()

with open("example.webp", "wb") as f:
    f.write(res.content)
Capabilities

What you get

The things that usually take a week of fighting a headless browser, already handled.

Real browser rendering

Pages are rendered by an actual browser engine, so JavaScript, web fonts, CSS grid and lazy images all behave the way they do for a visitor.

Full-page capture

One parameter captures the entire scrollable page, not just the viewport. Height is bounded so a runaway page cannot produce a runaway file.

Viewport control

Any width and height up to 3840×4320, device scale up to 3×, a dark-mode flag, or a device preset that renders as a real phone or tablet.

PNG, JPEG, WebP and PDF

Pick the format per request with adjustable quality, or format=pdf for the page printed with working links and selectable text.

Locked down by default

Requests aimed at private networks, loopback or cloud metadata are refused, redirects and subresources included. The browser runs sandboxed, unprivileged, with every capability dropped.

What changed

One call renders a page against another URL or a stored baseline and returns the changed regions as numbers plus a diff image, posted to Slack if you like. Staging against production, or a page against last week.

Honest quotas

Every response carries your remaining balance in a header, and a render that fails on our side is refunded automatically.

Reference

Parameters

All optional except url. Out-of-range values are clamped rather than rejected. Full reference →

ParameterDefaultDescription
url—The page to capture. Must be http or https.
width1280Viewport width in CSS pixels, up to 3840.
height800Viewport height in CSS pixels, up to 4320.
full_pagefalseCapture the whole scrollable page.
formatpngOne of png, jpeg, webp, pdf.
device—iphone-15, pixel-8, ipad, laptop or desktop: viewport, density, touch and user agent.
steps—Up to 20 actions before the capture: click, type, press, hover, scroll, wait, wait_for. How →
quality851–100, for jpeg and webp.
scale1Device pixel ratio, up to 3 for retina output.
darkfalseRender with a dark colour scheme preference.
delay0Extra wait in milliseconds before capture, up to 10000.
cookies, header, basic_auth—Reach pages behind a login. Each is scoped to the target host only. How →
Pricing

Simple plans, honest quotas.

Monthly renders and snapshot sets, no per-seat charges and no annual lock-in. Start free and move up when you outgrow it. Failed renders are refunded.

Free
$0
100 renders / month
  • 1 snapshot set, daily checks
  • All formats and options
  • 2 renders at once
Start free
Starter
$9 / mo
2,000 renders / month
  • 5 snapshot sets
  • Hourly schedules
  • 2 renders at once
Start free
Team
$49 / mo
25,000 renders / month
  • 50 snapshot sets
  • Deploy checks for every project
  • 3 renders at once
Start free
Business
$149 / mo
100,000 renders / month
  • 200 snapshot sets
  • 3 renders at once
Start free
Use cases

What people build with it

Every one of these ends up needing the same thing: a reliable picture of a web page, produced on demand and without running browser infrastructure.

Social cards and link previews

Generate Open Graph images from a live page instead of maintaining a separate template. The card on this very site was produced by this API.

Visual change monitoring

Capture a page on a schedule and diff the images to catch layout regressions, silent content edits, or a competitor quietly changing their pricing.

Thumbnails at scale

Directories, marketplaces and link aggregators need a preview for every listing. One request per URL, no queue to run.

Reports and archiving

Attach a rendered snapshot to an audit trail, an invoice, or a compliance record, so what a page said on a given date is not a matter of memory.

Design and QA review

Render the same page at several widths and device scales in one pass to see what actually ships on a phone, a laptop and a retina display.

Documentation that stays current

Screenshot your own product as part of a build step, so the images in your docs are never three releases out of date.

FAQ

Questions

If something here is not covered, the documentation goes deeper.

How fast is a typical render?

Most pages come back in well under a second. A render is a real page load, so a heavy site with large images and third-party scripts takes longer than a lean one. Every response carries an X-Render-Time-Ms header so you can measure it yourself rather than take our word for it.

Does it run JavaScript?

Yes. Pages are rendered by a real browser engine, so single-page apps, client-side routing, web fonts, CSS grid and lazy-loaded images all behave the way they do for a visitor. If a page needs a moment to settle after load, the delay parameter waits before capturing.

What happens when a page fails to load?

You get a 502 with a machine-readable error field, and the render is not counted against your quota. Failures on our side are refunded automatically, so you are never billed for our problems.

Can I capture the whole page, not just the viewport?

Set full_page=true and the capture covers the entire scrollable height. The result is bounded at 4320 pixels tall so a page with an infinite-scroll footer cannot produce an unbounded file.

Do you support retina output?

Use scale=2 for a 2x device pixel ratio, or scale=3 for 3x. A 1280-wide viewport at scale=2 produces a 2560-pixel-wide image with crisp text, which is what you want for a high-density display.

Can I use the API directly in an img tag?

Yes. Pass your key as a ?key= query parameter and point an img element straight at the endpoint, because the response body is the image itself rather than JSON containing a link. Be aware this exposes the key to anyone who reads the page, so use a key you are willing to rotate.

What can I not screenshot?

Anything on a private network. Requests to loopback, RFC1918 ranges, link-local addresses and cloud metadata endpoints are refused, including hostnames that resolve to them. If you need a screenshot of an internal tool, it has to be reachable from the public internet first.

Is the free tier really free?

One hundred renders a month, no card, no trial clock. Every parameter works on the free plan, and the only difference between tiers is how many renders, snapshot sets and renders at once you get.

When does my quota reset?

At the start of each calendar month, UTC. Unused renders do not roll over, and you can check what is left at any time from the dashboard or the X-Quota-Remaining header.

Start with a hundred free renders.

No card, no trial clock. Sign in with a link, create your key on the dashboard, and the MCP connection is one URL away.

By signing in or creating an account you agree to the Terms of Service and the Privacy Policy.