Back to blog

Capture guides

How to Capture a Webpage Screenshot Programmatically (URL to Image via API)

July 27, 2026 · 6 min read · Grabbit Team

How to Capture a Webpage Screenshot Programmatically (URL to Image via API)

To capture a webpage screenshot from your code, send the page URL to a screenshot API and it returns a hosted image. One HTTP request in, one image URL out. The headless browser that renders the page runs in the cloud, so there is no Chromium to install and no browser process to keep alive.

That is the fast path. Below are the ways to capture a webpage, when each one fits, and how to get the full-page, format, and timing options right.

The quick answer

If you just want a URL captured as an image from your code, this is the whole thing:

curl https://api.grabbit.live/v1/grabs \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "width": 1280,
    "height": 720,
    "format": "webp"
  }'

The response is JSON with a hosted image_url:

{
  "id": "grb_01jx...",
  "status": "done",
  "target_url": "https://example.com",
  "image_url": "https://cdn.grabbit.live/grabs/grb_01jx....webp",
  "width": 1280,
  "height": 720,
  "format": "webp",
  "bytes": 62140,
  "execution_ms": 940,
  "created_at": "2026-07-27T09:00:00.000Z"
}

Store that image_url, embed it, or hand it to another service. The rest of this guide is about picking the right method and getting the capture right.

Manual versus programmatic capture

"Capture a webpage screenshot" splits into two different jobs, and the right tool depends on which one you have.

Manual, one page. You are looking at a page and want to save it. Your browser already does this. In Chrome or Edge, open the command menu with Ctrl+Shift+P (Cmd+Shift+P on Mac), type "screenshot," and choose "Capture full size screenshot" for the whole page. Edge has a dedicated shortcut: Ctrl+Shift+S, then "Capture full page." An extension like GoFullPage does the same through a toolbar button. For one page you are looking at right now, use one of these and move on.

Programmatic, repeatable. You need to capture pages from code, on a schedule, or across many URLs. The manual path falls apart here: you cannot click a browser menu inside a cron job, a CI pipeline, or a webhook handler. You need an endpoint you can call. That is the rest of this guide.

Capturing a webpage with an API

For anything repeatable, a screenshot API is the shortest path. You already saw the curl call. Here is the same capture in a few languages, since "how do I do this in my stack" is the real question.

Python, using requests:

import requests

resp = requests.post(
    "https://api.grabbit.live/v1/grabs",
    headers={"Authorization": "Bearer sk_live_..."},
    json={
        "url": "https://example.com",
        "width": 1280,
        "height": 720,
        "format": "webp",
    },
)
data = resp.json()
print(data["image_url"])

Node.js, using the built-in fetch:

const resp = await fetch('https://api.grabbit.live/v1/grabs', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer sk_live_...',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://example.com',
    width: 1280,
    height: 720,
    format: 'webp',
  }),
});
const data = await resp.json();
console.log(data.image_url);

Every one of these is a plain HTTP call. No chromedriver, no 300 MB Chromium download, no async browser session to tear down. That is the whole reason to reach for an API over a local capture: the rendering machinery lives somewhere else.

Capturing the full page, not just the viewport

By default a capture stops at the viewport height you request. To grab the entire scrollable page as one tall image, set full_page to true:

curl https://api.grabbit.live/v1/grabs \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "width": 1280,
    "full_page": true,
    "format": "webp"
  }'

With full_page on, height is ignored and the render extends to the bottom of the document. This is the "scrolling screenshot" people ask for: everything below the fold, in one image. width must be between 320 and 1920 pixels; height, when you use it, between 240 and 1080.

Handling pages that load content late

The reason a real browser beats a raw-HTML fetch is that it runs JavaScript. Single-page apps, lazy-loaded images, and content that appears a beat after load all render the way they do for a visitor, because the capture happens in headless Chromium, not an HTML parser.

Two options control the timing:

  • delay_ms waits a fixed number of milliseconds (0 to 10000) after load before firing the capture. Use it when content animates or streams in.
  • selector waits for a specific element to appear and captures once it does. Use it when you know the exact node that signals "the page is ready."
curl https://api.grabbit.live/v1/grabs \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/dashboard",
    "width": 1440,
    "height": 900,
    "delay_ms": 1500,
    "format": "png"
  }'

This is also why an API can capture pages where a browser extension fails. A page can break extension-based capture with its layout, but a server that loads the URL like a normal visitor still gets a clean render of what the browser paints.

Choosing PNG, JPEG, or WebP

The format field takes png, jpeg, or webp, and picking wrong means either bloated files or lost quality.

  • WebP is the best default. For a typical webpage render it produces the smallest file at the same visual quality, which adds up fast when you store and serve thousands of captures. Use it unless you have a reason not to.
  • PNG is lossless and supports transparency. Reach for it when exact pixel fidelity matters, for example a baseline image in a visual regression test.
  • JPEG is the safest bet for older tooling that predates WebP. It is lossy, so text edges soften slightly.

Switching format is a one-word change in the request body, so you can experiment without rewriting anything.

When a local capture is the better call

An API is not always the answer. Capture locally instead when:

  • You are doing a single manual capture. Use the browser shortcut from earlier.
  • You already have the HTML, not a URL. If the markup lives in your app and is never served at an address, a local render avoids a round trip. See HTML to image for that pattern, including hosting your template at a URL and capturing it.
  • You cannot make outbound requests. In an air-gapped environment an API is off the table, so a bundled headless browser is the only option.

For everything else, especially anything on a schedule or in CI, the API path keeps your deployment small and removes a whole class of "it works locally but not in the container" failures.

Pricing is worth a word here because it is where these tools differ most. Grabbit charges a flat $0.002 per live capture as prepaid credits that never reset or expire monthly, so a batch that runs once a quarter does not forfeit an unused monthly allowance. That is different from the metered monthly quotas most screenshot tools bill on.

Next steps

The screenshot API covers the full parameter set, authentication, and rate limits. If you are wiring this into a job, the screenshot from a URL guide walks the request end to end, screenshot automation covers running captures on a schedule without a browser, and screenshot a list of URLs handles capturing many pages at once.

FAQ

How do I capture a screenshot of an entire webpage?
For a one-off, your browser already does it: in Chrome or Edge open the command menu with Ctrl+Shift+P (Cmd+Shift+P on Mac), type screenshot, and choose Capture full size screenshot. To capture the entire page from code, send the URL to a screenshot API with full_page set to true. It runs a real headless browser in the cloud and returns one tall image covering the full scrollable height, with nothing to install locally.
How do you take a screenshot of a web page?
You have two paths. Manually, use your browser's built-in capture (Ctrl+Shift+S in Edge, or the DevTools command menu in Chrome) or an extension like GoFullPage. Programmatically, POST the page URL to a screenshot API and it returns a hosted image_url. The manual path is for one page you are looking at right now; the API path is for capturing pages from a script, a cron job, or across many URLs.
How do I capture a screenshot on a website that blocks it?
Some pages block browser extensions or use CSS that breaks extension-based capture, but they cannot block a server that loads the page like a normal visitor. A screenshot API renders the page in real headless Chromium, so it captures what a browser would actually paint, including sites where a capture extension fails. It only works on pages the service can reach over the public internet, not on a page behind your own login unless you pass the right headers or cookies.
How do I capture a scrolling (full-page) screenshot?
A scrolling screenshot is just a full-page capture. In the browser, the DevTools Capture full size screenshot option or Edge's Capture full page does it. From code, set full_page to true in the API request and the capture extends past the viewport to the bottom of the document instead of stopping at the fold, producing a single tall image of the whole page.
How do I capture a webpage screenshot without installing a browser?
Use a screenshot API. The headless browser that does the rendering runs on the service's infrastructure, so your code makes a plain HTTP request and gets back an image URL. There is no Chromium binary to download, no chromedriver to match to a browser version, and no browser process to keep alive between captures.

Capture any website with one API call

Get a free test key and capture your first screenshot in two minutes.

Written by

Grabbit Team

Screenshots as a service

The team behind Grabbit, the screenshot API for developers and AI agents. We write about web capture, rendering, and automating screenshots at scale.

Keep reading