Full Page Screenshot API for Lazy-Loaded Pages avatar

Full Page Screenshot API for Lazy-Loaded Pages

Pricing

from $8.00 / 1,000 screenshots

Go to Apify Store
Full Page Screenshot API for Lazy-Loaded Pages

Full Page Screenshot API for Lazy-Loaded Pages

Full page screenshot API with a completeness check: it scrolls each page so lazy-loaded sections appear, finds blank bands in the image, repairs them and scores the result from 0 to 100. A page it cannot capture costs nothing.

Pricing

from $8.00 / 1,000 screenshots

Rating

0.0

(0)

Developer

Kesav Kumar Jayakumar

Kesav Kumar Jayakumar

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Categories

Share

What does Full Page Website Screenshot do?

Full Page Website Screenshot takes a full-page screenshot of a public web page, including the parts that only load as a visitor scrolls, and tells you whether the image is complete. Give it a list of URLs. It opens each page in Chrome, scrolls in steps so lazy-loaded images and scroll-triggered sections appear, captures the whole page from the top, then scans the image for blank areas and repairs them. With the default settings every captured page gets a completeness score from 0 to 100 and a plain status, so you know which screenshots to trust without opening them one by one. The score is left empty when you turn off the check for blank areas, choose the simple capture strategy or capture only the first screen. A page that could not be captured has no image and no score: its row carries a status and a reason instead. You pay only for pages it captured. A page that is blocked, fails to load or is disallowed by robots.txt costs nothing.

Use it as a screenshot API: start it from code, a schedule or an integration, then fetch the images and the result table over HTTP. It works on public pages only. It does not log in, take cookies from you, solve CAPTCHAs, hide that it is an automated browser or get around bot protection. When a site refuses access, the row says so and you pay nothing for it.

Why use Full Page Website Screenshot?

A plain full-page screenshot breaks on modern sites. Images wait for a scroll before they load, and sections fade in only while they are on screen. The picture comes back with white holes, sometimes thousands of pixels tall, and nothing tells you. In our 20-site test, a plain full-page capture left a blank band of 500 px or more on 7 sites. This Actor scrolls the page the way a visitor would, scans the finished image for gaps and repairs them. On those same 7 sites the scroll pass and the repair pass together removed the gap on 5, in each of four live runs. On the other 2 (gsap.com and lenis.darkroom.engineering) a gap stayed in every run, and the Actor reported it with the status partial, a completeness score and the position of the band instead of hiding it. In one of the four runs a further site (theguardian.com) kept a band too. The Actor does not promise a complete image on every page. It tells you which ones are not.

What you get:

  • Fewer blank gaps on lazy-loaded and scroll-animated pages. The Actor scrolls in steps, promotes lazy images, waits for images and fonts, then captures from the top.
  • A completeness check on every full-page image at the default settings. Tall blank bands are found and re-captured by scrolling back to them. Bands that stay blank are listed with their position instead of being hidden.
  • Honest statuses. ok, partial, blocked, failed or skipped, each with a reason. Only ok and partial screenshots are charged.
  • Control over the capture. Viewport size, retina pixel ratio, phone emulation, dark mode, PNG, JPEG or WebP, cookie banner hiding, hidden elements, a wait for a selector.
  • Tall pages. Pages are captured in tiles and stitched, so a tall page comes out as one image. The default cut is 20,000 px. A 30,000 px page is stitched correctly once maxPageHeight is raised, which the setting allows up to 60,000 px.

Each claim above has a test behind it:

What you getHow it worksThe test that backs it
Blank gaps found and repairedSteps through the page, loads data-src and native lazy images, re-captures blank bands it finds and reports any band it could not fill, with its position.Four live runs on 20 public sites on 11 Oct 2026 (gate-final-e, gate-final-f, gate-verify-k1, gate-audit-g): a plain full-page capture left a band of 500 px or more on 7 sites, the Actor removed the gap on 5 of them in every run and marked the other 2 partial. Local tests: "data-src and native lazy images all load" and "reveal-on-view sections that hide again on leave are repaired into the full image".
No charge for a page it did not captureBlocked, failed, HTTP-error, robots-disallowed and unsafe-address rows are written with a reason and are not charged."B1 one screenshot event is charged per delivered result, and failed, blocked and skipped rows are not charged".
A spending cap that stops the runSet a maximum cost per run. The run stops before it charges past it, and every URL it did not reach gets a skipped row."P6 the maximum charge per run stops the run cleanly: no screenshot is charged past the limit", and the same at three pages at a time.
robots.txt always respectedThere is no switch to turn it off. A disallowed URL is skipped, listed and not charged. A robots.txt that cannot be read closes the site."robots.txt is always honoured, even if a user sends respectRobotsTxt false" and the robots.txt tests of the review fixes.
No requests to private networksLocalhost, private ranges and cloud metadata addresses are refused, also when a public page redirects there or embeds them, and in other spellings of the same address.The three I7 tests: a redirect to an internal address, the same over https, and an embedded frame or image. A full-width or ideographic-dot spelling of 127.0.0.1 is refused too.
Restarts that never charge twiceWhen the platform migrates or aborts a run, the counters are saved. A result already delivered is not captured or charged twice. An aborted run stops where it is, so URLs it had not reached get no row."P1 on migrating the run saves its summary and state..." and "P2 on aborting the run saves a summary and exits well inside 30 seconds...", both driven by the platform's own events.

Plus what the Apify platform adds around it:

  • API access. Start runs and read results with the Apify API or the JavaScript and Python clients.
  • Scheduling. Run it hourly or daily to archive pages or watch them change.
  • Integrations. Send results to Make, Zapier, Google Sheets, Slack or any webhook.
  • Monitoring. Run history, logs and alerts for failed runs.

Typical uses are page archives for compliance, visual checks of landing pages on desktop and phone, competitor page monitoring, link preview thumbnails and design research boards.

What data can Full Page Website Screenshot extract?

Each URL becomes one row in the dataset. The most useful fields:

FieldTypeWhat it holds
urlstringThe URL you asked for.
statusstringok, partial, blocked, failed or skipped.
screenshotUrlstringLink to the image file in the run's key-value store.
completenessScoreintegerShare of the image that is not blank, 0 to 100. It is null on a row without an image, and when the check did not run (check for blank areas off, simple strategy, or first screen only).
titlestringPage title, cleaned and cut to 300 characters.
httpStatusintegerHTTP status code of the page.
widthPx, heightPxintegerImage size in device pixels.
blankBandsarrayBlank bands left in the image, as pixel ranges from the top.
qualityFlagsarrayNotes such as blank-band-remaining, images-pending, height-capped, http-error-status or internal-request-blocked.
durationMsintegerTime spent on this URL.
errorstringWhy a URL has no screenshot, in a sentence for people.
errorCodestringA short code for the same reason, for counting rows by cause. It is null on a captured page. The codes are listed below.

Every row that has no screenshot carries one of these codes in errorCode, so you can count rows by reason without reading the sentence. The sentence in error can be reworded in a later version. The code stays.

errorCodeMeaning
robots-disallowedThe site's robots.txt does not allow the page, or a redirect led to a path it does not allow.
robots-unreadableThe robots.txt of the site could not be read, so the site is treated as closed.
private-addressThe address, a redirect or the robots.txt address leads inside a network.
invalid-urlThe text is not a web address, or is longer than 2,048 characters.
duplicateThe same page appears earlier in the list.
charge-limitThe run reached the maximum cost per run before this URL.
run-time-limitThe run reached its time limit before or while this URL was captured.
repeated-timeoutsThe run stopped after several pages in a row ran out of time.
run-endedThe run ended while this page was being captured.
blockedThe site answered with an access-denied or bot-check page.
http-errorThe page answered with an HTTP error status such as 404 or 500.
dns-errorThe domain name does not exist.
connection-failedThe server refused or closed the connection.
unreachableThe server could not be reached.
tls-errorThe site certificate is not valid.
redirect-loopThe page redirects in a loop.
downloadThe URL is a file download, not a web page.
page-timeoutThe page did not finish loading in time.
capture-timeoutThe capture took longer than the time limit per page.
selector-invalidThe waitForSelector value is not a valid selector.
too-largeThe page transferred more data than one page may (500 MB).
otherAny other reason. The sentence in error says what happened.

How to take a full page screenshot of a website

  1. Open the Actor in Apify Console and select the Input tab.
  2. Add the pages you want under Page URLs. The form is prefilled with two example pages, so you can press Start to see a result straight away.
  3. Choose the Image format and the viewport. The defaults give a PNG at 1280 px wide.
  4. Keep Check for blank areas and Repair blank areas on. They are what makes the image complete.
  5. Press Start. In our local tests a typical page took about 14 seconds (median 12.1 to 14.1 s over four runs on a laptop limited to one CPU) and the heaviest animated page in the test, a WebGL site, 61 to 100 seconds. These figures come from that laptop, not from the Apify platform, where the time may be shorter or longer.
  6. Open the Output tab for the table with every screenshot, or the Storage tab to download the images. Export the table as JSON, CSV or Excel.

To run it from code, send the same input to the Actor through the API:

{
"startUrls": [{ "url": "https://apify.com" }, { "url": "https://en.wikipedia.org/wiki/Web_scraping" }],
"format": "jpeg",
"quality": 85,
"viewportWidth": 1440,
"colorScheme": "dark"
}

How to save screenshots to Google Sheets, Google Drive or Slack (Make, Zapier, no code)

A common use is a weekly archive of the same pages, such as your own pricing page or a set of landing pages. Create a schedule with your list of URLs, then pass each run's results on.

Slack, built in. On the Actor's Integrations tab, add Slack, connect your workspace, pick a channel and choose the event "Run succeeded". Each finished run posts a message with a link to its results.

Google Sheets or Drive with Make.com.

  1. In Make, create a scenario and add the Apify module that watches for finished Actor runs, set to this Actor.
  2. Add the Apify module that gets dataset items, and map the run's default dataset ID.
  3. Add Google Sheets "Add a Row" with url, title, screenshotUrl and completenessScore, or an HTTP "Get a file" step on screenshotUrl followed by Google Drive "Upload a File" to keep the images themselves.

Zapier. Use the Apify trigger for a finished Actor run, then the Apify step that fetches dataset items, then a Google Sheets "Create Spreadsheet Row" or a Slack "Send Channel Message" action.

Your own code. Add a webhook on the Integrations tab for the event "Run succeeded", and read the dataset from the URL in the payload.

How much does it cost to take a full page screenshot?

You pay per screenshot, and the Apify platform usage for the run is included, Apify Proxy traffic too. A screenshot costs $0.02 on the Free and Bronze plans, so 1,000 pages cost $20.

EventWhen it is chargedPrice
screenshotOne captured page with status ok or partial$0.02 (Free, Bronze), $0.018 (Silver), $0.016 (Gold)
Actor startOnce per run, scaled by memory (Apify standard event)$0.00005 per GB of memory

Pages that are blocked, fail to load, return an HTTP error such as 404 or 500, are skipped by robots.txt or are rejected as unsafe addresses cost nothing. Silver and Gold plans pay less per screenshot, as the table shows. Bronze pays the same as Free. You can cap a run with the Maximum cost per run setting, and the Actor stops cleanly at that limit.

How much does one screenshot cost?

One screenshot costs $0.02 on the Free and Bronze plans, $0.018 on Silver and $0.016 on Gold. A run adds a start fee of about $0.0002 at the default memory. The price already includes the Apify platform usage and any Apify Proxy traffic, so there is no second bill for compute. A run of 100 pages costs about $2. You can set Maximum cost per run to cap the spend, and the Actor stops cleanly when the cap is reached.

How do I keep a run within budget?

Set Maximum cost per run when you start it. The run stops before it would charge past that amount, and every URL it did not reach gets a skipped row with the code charge-limit, so nothing is lost silently. Capturing many URLs in one run pays the start fee once.

What does the price pay for?

Each page gets a scroll pass, a wait for images and fonts, a scan for blank areas, a repair pass where needed and a completeness score. Heavy animated pages take longer than plain ones, and the price stays the same for both. A partial result is a saved image with a known gap, and it is charged, because it is a usable capture. The flags in qualityFlags and the positions in blankBands say where the gap is.

Input

Open the Input tab to see every setting with a short description. The first fields are startUrls, fullPage (capture the full page, on by default), format (PNG, JPEG or WebP) and quality (for JPEG and WebP). The form has four groups after them:

  • Viewport and device: viewportWidth, viewportHeight, deviceScaleFactor (pixel ratio), mobile (phone emulation) and colorScheme.
  • Completeness check: captureStrategy, verifyCompleteness, repairBlankAreas, blankAreaThresholdPx and scrollDelayMs.
  • Page loading: waitUntil, waitForSelector, extraDelayMs, maxPageHeight, captureErrorPages, hideCookieBanners, hideSelectors and freezeAnimations.
  • Limits and proxies: maxConcurrency, timeoutSecs and proxyConfiguration (Apify Proxy with data center addresses only).

startUrls accepts plain URLs, added one by one or pasted with Bulk edit, one per line. A link to a text file is not supported: the run stops at once with a message that asks you to paste the URLs, because the Actor does not download lists from addresses it has not checked. One run takes at most 1,000 URLs, so split a bigger list into several runs, and a URL longer than 2,048 characters is skipped with a row that says so. A URL that appears more than once is captured once, and each extra copy gets a skipped row that names the first one. Set captureStrategy to simple for a single plain shot when speed matters more than completeness.

Output

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel. The screenshots are separate files in the run's key-value store. A run also writes a SUMMARY record with the counts of captured, partial, blocked, failed and skipped URLs. Every URL of a valid list gets exactly one row, also when the run stops early at the cost cap, after five timeouts in a row or near the time limit of the run: the URLs it did not reach get a skipped row that says why. A list that is empty or has a blank address is refused before anything runs. A run that the platform kills from outside, for example because it ran out of memory, can leave URLs without a row; start it again and the results already delivered are kept. A run in which no page could be captured ends with the status Failed and the most common reason in its message, and the rows stay in the dataset. If a run is restarted, a result that was already delivered is not captured or charged a second time.

A captured page and a blocked page look like this:

[
{
"inputIndex": 0,
"url": "https://example.com/pricing",
"finalUrl": "https://example.com/pricing/",
"httpStatus": 200,
"title": "Example Pricing Page",
"status": "ok",
"screenshotUrl": "https://api.apify.com/v2/key-value-stores/exampleStoreId0001/records/screenshot-3f2a9c1b7d4e.png",
"format": "png",
"widthPx": 1280,
"heightPx": 5240,
"bytes": 842113,
"blankBands": [],
"blankBandsFound": 2,
"blankBandsRepaired": 2,
"completenessScore": 100,
"qualityFlags": [],
"durationMs": 9400,
"error": null,
"errorCode": null
},
{
"inputIndex": 1,
"url": "https://example.org/members",
"httpStatus": 403,
"status": "blocked",
"screenshotUrl": null,
"completenessScore": null,
"error": "The site returned an access-denied or bot-check page. Not captured, not charged. The Actor does not retry through other networks or disguise itself.",
"errorCode": "blocked"
}
]

Tips for faster and cheaper screenshots

  • Capture several URLs in one run. The browser start and the Actor start charge are paid once per run, not once per page.
  • Use jpeg or webp with a quality near 80 when you do not need lossless images. On the 19 pages captured in one of our 20-site runs, JPEG at quality 80 was 3.6 times smaller than PNG at the median (range 0.8 to 7.7 times), and WebP 4.5 times smaller (range 0.9 to 8.9 times, on the 16 pages short enough for WebP). Pages that are mostly flat color or text gain little, and one came out larger as JPEG. WebP cannot hold an image taller than 16,383 px, so a taller page is saved as PNG and flagged format-fallback-png.
  • Lower scrollDelayMs for fast sites and raise it when lazy content arrives late. The default is 160 ms.
  • Set maxPageHeight to what you need. Endless feeds stop at that height instead of running for minutes.
  • Keep deviceScaleFactor at 1 unless you need sharp retina images. A ratio of 2 gives four times the pixels and needs more memory and time. In our local test the widest setting (3840 px at a ratio of 3, an image of 100 million pixels) peaked at about 3.2 GB for the whole browser, against about 2.5 GB for the default settings, so give a run with such settings the 8,192 MB option. A heavy animated page at a ratio of 3 also ran past the 150 second limit once on one CPU, and that page was not charged.
  • Use hideSelectors for chat widgets and sticky bars, and waitForSelector when a page paints its main content late.
  • Raise maxConcurrency only together with the Actor memory setting. Every parallel page opens its own browser tab, and the Actor holds the number to the run memory divided by 1 GB.

FAQ, disclaimers and support

Taking a screenshot of a public page is what any visitor's browser does, but the law depends on the site, the content and what you do with the image. Terms of use, copyright and database rights can apply to the pages and to how you reuse the pictures. Check them for your use case. Images, text and logos on a page usually belong to the site or to others. You are responsible for how you use the screenshots. Do not use the Actor to capture illegal content; report misuse to Apify at legal@apify.com. This is general information, not legal advice.

Does Full Page Website Screenshot respect robots.txt?

Yes, always. URLs that a site's robots.txt disallows are skipped, listed with the status skipped and not charged, and so is a page that redirects to a closed path. The Actor reads the file under its own name, FullPageWebsiteScreenshot, not under a browser name, and follows RFC 9309: a file that answers with a 4xx code means the site has no rules, and a file that cannot be read (a server error or no answer after one retry) means the site is closed, so its pages are skipped with the reason and not charged. If you own a site and want it captured, allow the path in its robots.txt.

Why is my screenshot marked partial?

A partial row means the image was saved but something is known to be incomplete. Look at qualityFlags: blank-band-remaining (a blank area survived the repair, with its position in blankBands), images-pending (images were still loading) or wait-selector-timeout (your selector never appeared). The image is still charged, because it is a usable capture. Raise scrollDelayMs, add an extraDelayMs, or raise blankAreaThresholdPx if the page has large solid-color sections on purpose.

Why was my URL blocked?

Some sites answer automated browsers with an access-denied or bot-check page. The Actor does not try to defeat that. The row gets the status blocked, and nothing is charged. The Actor does not retry through other networks or disguise itself.

Are error pages such as 404 charged?

No. A URL that answers with an HTTP error (404, 410, 500 and similar) gets the status failed with the code in the error field, and nothing is charged. This keeps a mistyped URL from costing you money. Turn on captureErrorPages to take the screenshot anyway. Those pages are then charged like any other, and flagged http-error-status.

Does it open private or internal addresses?

No. The Actor refuses addresses inside a network (localhost, private ranges, cloud metadata addresses), also when a page redirects there or embeds them, and also for the robots.txt request. Every request the Actor makes, the browser's and its own, goes through the same address check. Such a URL gets the status skipped and is not charged. An embedded item that points inside is left out of the image, and the row carries the flag internal-request-blocked.

Can it capture pages behind a login?

No. It captures what a visitor sees without signing in. It takes no cookies, passwords or tokens from you and never signs in.

What happens when a run reaches its time limit?

The Actor reads the time limit of the run from the platform. About two and a half minutes before it, no new page is started. Pages in progress get until 30 seconds before the limit to finish, and then every URL that was not delivered gets a skipped row that says the run reached its time limit, so you can run those URLs again. Nothing is charged for them. Set a longer Timeout in the run options for a long list: at about 20 seconds a page, 1,000 URLs need hours.

How long can one page take?

One attempt takes at most 250 seconds with the defaults. That is 90 seconds for loading (60% of Time limit per page, up to 90 seconds), 150 seconds for the capture after it (the full Time limit per page) and 10 seconds that the browser library adds around the two. The robots.txt read of a site happens inside that same bound, so a slow robots.txt cannot add to it. A page that runs out of time is not retried and is not charged, and five of them in a row stop the run. A page that fails fast for a reason that can change, such as a dropped connection, is tried once more.

What if a page never stops sending data?

A page that sends more than 500 MB while it loads is closed. Its row gets the status failed and the code too-large, it is not tried again and it is not charged. The 20 sites in our test sent 127 MB in total, so a normal page stays far below the limit.

How tall can a page be?

By default the image is cut at 20,000 CSS pixels, and maxPageHeight can raise that to 60,000. Very tall pages at a high pixel ratio are cut earlier, at about 100 million pixels per image, to keep the run inside its memory. A cut page gets the flag height-capped.

Can I schedule screenshots and send them to other apps?

Yes. Use Apify schedules for recurring runs, and integrations or webhooks to pass the dataset to Make, Zapier, Google Sheets, Slack or your own endpoint. The same runs are available through the API.

What if something looks wrong?

Open the Issues tab on the Actor page and describe the URL, your input and what you expected. A run link helps. Issues are answered within two days.

Is personal data involved?

A screenshot shows whatever the page shows, which can include names, faces, email addresses or other personal data. The Actor stores the image, the page title and technical details of the capture. It does not pull personal data out into fields, sign in, or accept consent banners; hiding a banner only hides it from the picture. Under the GDPR and similar laws you are the controller of what you capture, so you need a lawful reason to capture and keep pages that show people, and archiving or journalism may carry their own rules.

Other Actors by the same developer

  • SEC EDGAR Filing Monitor: new SEC filings for the tickers or CIKs you watch.
  • SEC Form D Feed: new private fundraising rounds filed with the SEC on Form D, with amounts and industry.
  • SEC XBRL Fundamentals: revenue, EPS, cash flow and other reported figures per company and period, from SEC XBRL filings.
  • UK Company Check: Companies House status, outstanding charges and risk flags for UK companies, or a list of newly registered ones.
  • US Trademark Status and Watch: USPTO status and upcoming deadlines for US trademarks, and what changed since your last run for marks you watch.
  • New Scholarly Papers Watch: papers new since your last run for the keywords, ORCID authors, journals, funders or DOIs you watch, from Crossref.