Website Screenshot Generator - $3.00 per 1,000 avatar

Website Screenshot Generator - $3.00 per 1,000

Pricing

from $3.00 / 1,000 screenshot takens

Go to Apify Store
Website Screenshot Generator - $3.00 per 1,000

Website Screenshot Generator - $3.00 per 1,000

Give it a list of URLs, get a rendered PNG or JPEG of each page: viewport or full page, 320-2560 px wide, 1x/2x/3x density, dark mode, mobile layout. A CSS selector takes out the cookie banner. One row per page: image link, final URL, title, status. Failed pages aren't charged.

Pricing

from $3.00 / 1,000 screenshot takens

Rating

0.0

(0)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Website Screenshot Generator

Give it a list of URLs and you get back a rendered picture of each page, plus a row of data about it: the URL it finally landed on, the page title, the HTTP status, the image dimensions, the file size and how long the render took.

Each page is opened in a real Chromium, so what you get is the page a visitor sees, with the JavaScript run and the lazy images pulled in. You set the viewport, whether it's the first screen or the whole scrolled page, the pixel density, dark mode, a mobile layout, and what gets taken off the page before the shutter fires.

Price

$3.00 per 1,000 screenshots, plus a $0.004 start fee per run.

ScreenshotsTotal
100$0.304
1,000$3.004
10,000$30.004

One screenshot-taken event per picture of the page you actually asked for. Not charged: the sample row, duplicate addresses (dropped before rendering), a page that timed out or refused, a page that answered with an anti-bot check instead of the page, and any page skipped because the run hit the size budget you set. Those all come back as rows with "charged": false so you can see what happened.

Filter on charged == true and the count equals what you were billed for.

Input

{
"urls": [
"https://www.python.org",
"https://developer.mozilla.org",
"https://news.ycombinator.com"
],
"viewportWidth": 1440,
"viewportHeight": 900,
"fullPage": false,
"format": "jpeg",
"quality": 80,
"removeSelectors": ["#cookie-banner", ".cookie-consent"],
"maxItems": 10
}
FieldWhat it does
urlsPages to photograph, one per line. A bare domain like example.com works. Up to 300 per run; duplicates dropped before anything renders.
maxItemsHard stop on how many pages this run captures, whatever the list length.
fullPageOff gives you the viewport. On scrolls the page and stitches it into one tall image, up to the height ceiling.
viewportWidth / viewportHeightThe window the page lays out in. 1440x900 is a laptop, 1920x1080 a desktop, 390x844 a phone. Width 320–2560, height 200–4000, and the schema rejects anything outside that.
deviceScaleFactor1 normal, 2 retina, 3 print. 2x is four times the file size, 3x is nine times.
darkModeTells the page the visitor prefers a dark scheme. Sites with a dark theme render in it; sites without look identical.
mobileTouch device profile and a mobile user agent, so you get the responsive layout. Pair with a narrow width.
format / qualityJPEG at 80 is the default and right for almost everything. PNG for lossless or a transparent background.
waitUntil / delayMs / navigationTimeoutMsHow ready the page must be, how long to pause after, when to give up. Raise delayMs for a heavy single-page app.
scrollToBottomScrolls to the foot first so lazy images below the fold are actually there. Turned on automatically with fullPage.
selectorA CSS selector to photograph one element instead of the page — a pricing table, a chart, a hero.
hideSelectors / removeSelectorsHide keeps the space, remove takes the element out of the layout. Remove is the one for cookie banners and pop-ups; hide is the one for a sticky header you want gone without the layout shifting.
customCssRaw CSS injected just before capture, up to 4,000 characters.
transparentBackgroundPNG only.
locale / timezoneen-US, Europe/Berlin. For sites that localise or print clocks.
maxFullPageHeightWhere a whole-page capture gets cut. Default 8,000 px, max 20,000.
maxTotalImageMbThe run stops writing images past this and says so in an uncharged row. Default 250 MB.
concurrencyPages rendering at once. 3 is a good balance. Drop to 1 if a site objects to several requests at a time.
useProxyOff by default, and off is usually right. Turn it on if a site answers the container with an anti-bot check instead of the page.
proxyUrlsYour own proxy servers, if you have them. Takes precedence over everything else. Metered per-gigabyte proxy groups are never used, whatever the input asks for.

Empty input gives you one labelled sample row, free.

Output

{
"ok": true,
"charged": true,
"recordType": "screenshot",
"url": "https://example.com/",
"screenshotUrl": "https://api.apify.com/v2/key-value-stores/r7tznlACMo9u7atq8/records/screenshot-001-example.com.jpg?signature=...",
"screenshotKey": "screenshot-001-example.com.jpg",
"finalUrl": "https://example.com/",
"title": "Example Domain",
"statusCode": 200,
"imageWidth": 1440,
"imageHeight": 900,
"format": "jpeg",
"fullPage": false,
"darkMode": false,
"deviceScaleFactor": 1,
"viewportWidth": 1440,
"viewportHeight": 900,
"pageHeight": 900,
"truncated": false,
"fileSizeBytes": 17536,
"loadTimeMs": 1220,
"scrapedAt": "2026-08-21T16:20:52.314Z"
}

Where the images live

Each picture goes into the run's key-value store. screenshotUrl is a direct HTTPS link you can put in an <img> tag, drop in a spreadsheet or fetch from a script; screenshotKey is the file name. File names are numbered by position in your list and tagged with the domain, so ten pages give you screenshot-001-example.com.jpg through screenshot-010-... and they sort the way you sent them.

The images last as long as your account keeps the run's data. On the free plan that's a limited window, so copy anything you want to keep into your own storage.

Keeping file sizes sane

Pictures get big faster than people expect. A whole-page capture of a long article at 2x is many times the size of that page's first screen at 1x, because you're multiplying the height by the density.

The defaults already lean small. JPEG at quality 80 is the one that matters most; it's visually clean and a fraction of the file at quality 100. Leave deviceScaleFactor at 1 unless somebody is going to zoom in. maxFullPageHeight cuts a whole-page capture at 8,000 px, which is what stops an infinite-scroll feed rendering until something gives way. maxTotalImageMb caps the run on top of all that.

Limits

  • Pages behind a login are out of scope. The run carries no accounts and no cookies, so it sees the logged-out page. A paywall or sign-in screen is what you'll get a picture of.
  • Some sites refuse automated browsers outright. Across a battery of 50 well-known public pages, 48 rendered and 2 answered with an anti-bot check — and those 2 still refused through the rotating pool, so the pool isn't the fix for them. Your own proxy servers in proxyUrls are. Either way you get the image of the block page and an uncharged BLOCKED row instead of a bill for a picture of the wrong thing.
  • Every page is stopped once it has painted rather than being allowed to load indefinitely. That's what keeps a batch of marketing sites from taking minutes each, but a page that fills in content after that point shows the state at the moment of the stop.
  • A full-page capture is cut at the height ceiling. An infinite-scroll feed always gets cut; the row says truncated: true and gives you the real pageHeight.
  • Video and audio are blocked, so an autoplaying hero video shows its poster frame. Analytics and session-recording scripts are blocked too — that doesn't change how a page looks, but a site that refuses to render until its tag manager loads is the rare exception.
  • PDFs and other non-HTML addresses aren't rendered. The browser treats them as a download and you get an uncharged NAV_ABORTED row.
  • Dark mode only asks the site for its dark theme. A site with no dark theme looks the same.
  • Fonts, ads and personalised content vary by where a request comes from, so two runs of the same page a day apart won't be pixel-identical. Compare content, not hashes.
  • Image dimensions cap at 16,000 px per side, and a total surface ceiling quietly lowers the full-page height when you combine a wide viewport with 3x density. The row reports what you actually got.
  • 300 pages per run is the hard ceiling.

Diagnostic codes

Uncharged rows carry "_diagnostic": true and an errorCode: BLOCKED (anti-bot check served instead of the page — the image is attached anyway so you can see it), NAV_TIMEOUT, DNS_FAILED, CONNECTION_REFUSED, TLS_FAILED, SELECTOR_NOT_FOUND, IMAGE_TOO_LARGE, BUDGET_REACHED, TIME_BUDGET. Each names the url it belongs to and says what to change.

Questions

How do I get rid of the cookie banner? Put its CSS selector in removeSelectors#onetrust-banner-sdk, .cookie-consent, whatever the site uses.

Why is my full-page screenshot cut off? It was taller than maxFullPageHeight, 8,000 px by default. The row says truncated: true. Raise it to 20,000 if you need the rest.

Will one broken page fail the run? No. It becomes an uncharged diagnostic row and the run moves on. A failed run would still bill the start fee, which would mean paying to be told something went wrong.

Can I schedule it? Yes. Nothing is held between runs. Keep the screenshotUrl off each run and you end up with a dated history of what the page looked like.