ScreenshotRender
← Back to blog
Tutorials

How to Screenshot Entire Webpage: 4 Methods That Work

Robert Belt·8 min read
Updated On :
Illustration of a tall scrolling webpage being captured as a single full page screenshot

Short answer: open the page in Chrome, hit Cmd+Shift+P, type Capture full size screenshot, and you have a PNG in two seconds. The rest of this post is why that quietly fails on every site that actually matters, and what to use instead.

By the end you will know which method survives lazy loading, sticky headers, and Cloudflare on real production sites, and which ones cut your screenshot in half without telling you.

There are four ways to screenshot an entire webpage in 2026: Chrome devtools, a screenshot extension, a headless browser like Puppeteer or Playwright, and a hosted screenshot API. They are roughly in order of effort, and almost exactly in reverse order of reliability. The two second devtools trick works on the static blog post you are reading right now. It does not work on most production pages. If you want one call that handles Cloudflare, cookie banners, and lazy loaded images for you, ScreenshotRender runs the whole pipeline behind a single GET request.

What counts as a full page screenshot?

A full page screenshot captures everything from the top of the document to the bottom of the scrollable area, not just the slice visible in the browser window. The visible slice is the viewport. The full document can be five or fifty times taller.

Three things make capturing the full document harder than it sounds. First, lazy loaded images do not exist in the DOM until they scroll into view, so a naive capture returns blank rectangles where photos should be. Second, sticky headers and fixed footers repaint as the page scrolls, and a stitched screenshot will show the header three or four times down the page. Third, on a retina display the device pixel ratio means a 1920 pixel wide page actually renders at 3840 actual pixels, which doubles file size and triples memory use. The MDN devicePixelRatio reference covers the math.

Every method below has to solve all three. Most of them only solve one or two.

How do you take a full page screenshot in Chrome without an extension?

Open devtools with F12, press Cmd+Shift+P (Ctrl+Shift+P on Windows or Linux), type Capture full size screenshot, and Chrome saves a PNG of the entire scrollable page to your downloads folder. No extension, no code, no waiting on a third party. The shortcut is documented in the official Chrome devtools command menu reference.

Try it on https://en.wikipedia.org/wiki/HTTP and it works in about two seconds, lazy loaded images and all, because Chrome itself walks the page before snapshotting.

Try it on a Cloudflare protected page like https://www.g2.com and it still works. You are a real browser with real cookies and real fingerprints, so Cloudflare lets you through. This is the trick: devtools only solves the problem for you, manually, on your own machine. It does not scale to a server, a cron job, or anything you want to share with a teammate.

Use it for personal notes. Use anything else for production.

Why do Chrome screenshot extensions fail on dynamic pages?

Most screenshot extensions scroll the page in chunks and stitch the viewport captures together, which breaks on three things: sticky headers, lazy loaded images, and pages that re-layout as they scroll.

The sticky header bug is the most visible one. A navigation bar with position: sticky appears in every chunk, so the stitched image shows the same header repeated five or ten times down the page. The lazy load bug is sneakier: an image two screens down loads the moment the extension scrolls to it, but the first chunk was already captured with a placeholder, so the stitched output has a gray rectangle where the photo should be.

Then there is the cookie banner. The EU consent popup sits on every chunk, so the final screenshot has six identical banners stacked down the page.

Extensions are fine for one off captures of a page you can eyeball before saving. They are not fine for monitoring, automation, or anything a customer will see.

How do you take a full page screenshot with Puppeteer or Playwright?

Launch a headless Chromium, navigate to the URL with page.goto(url, { waitUntil: 'networkidle0' }), then call page.screenshot({ fullPage: true }) and you have the PNG in memory. Both libraries expose the same primitive. See the Puppeteer Page.screenshot reference and the Playwright Page.screenshot reference.

The fullPage: true option is the one that does the work. Without it you get the 1280 by 720 viewport. With it the library scrolls the page, resizes the viewport to the full document height, captures, then resets. That handles lazy load and sticky headers correctly, which puts headless Chromium ahead of every extension.

It also adds three real costs. The first is install size: the Chromium binary is around 170 MB on Linux, which makes Lambda or Cloud Run deployments painful. The second is memory: one warm Chromium uses 300 to 500 MB of resident memory per concurrent screenshot, so a cheap server caps out at three or four parallel jobs. The third is fonts. A bare Linux container ships with no fonts, so any page using Inter or Noto renders in Times New Roman until you install the font packages yourself.

And then there is Cloudflare.

Skip the Chromium build, the Cloudflare fight, and the EC2 fleet.

One HTTP GET to ScreenshotRender returns a full page PNG with cookie banners and ads already stripped. No headless browser to maintain, no font packages to install, no 170 MB Chromium binary in your Docker image.

Try a render

When does headless Chrome still get blocked on production sites?

On any site running Cloudflare Bot Management, DataDome, PerimeterX, or Akamai Bot Manager, vanilla headless Chromium gets a 403 or a JavaScript challenge page roughly every request. Bot vendors look for navigator.webdriver === true, missing plugin arrays, off the shelf TLS fingerprints, and the standard Puppeteer launch flags. The Cloudflare Turnstile documentation spells out the signals.

Beating the detection takes a stealth plugin, a residential proxy, regularly rotated user agents, and the patience to update all three every time Cloudflare ships a new rule. Most teams burn a quarter on this before they outsource it.

There are smaller failure modes too. Intersection observers that wait on requestIdleCallback never fire in a headless browser running at 4x speed. Cookie banners that wait for a real user gesture stay on screen forever. Custom fonts time out and fall back to serifs. Each one is a one line fix once you know it exists, and a two hour debugging session before then.

How do you screenshot any webpage with one API call?

Send one HTTP GET to ScreenshotRender's endpoint with fullPage=true and you get back a hosted PNG URL with the whole page rendered, cookie banners removed, and ads stripped. The entire request is one line you can copy:

https://screenshotrender.com/api/v1/screenshot?apiKey=YOUR_API_KEY&url=https://en.wikipedia.org/wiki/HTTP&fullPage=true

Four parameters do the work. apiKey is your sr- prefixed key from the dashboard. url is the page to capture, URL encoded if it has its own query string. fullPage=true switches from the 1280 by 720 viewport to the full document height. wait takes a millisecond value if you need to give a single page app extra time to settle, and timeout caps the whole request.

Cookie banners, GDPR consent popups, ad overlays, and chat widgets are removed automatically before every capture, on every plan including the free one. That alone deletes the biggest class of full page screenshot bugs. For Cloudflare and similar bot challenges, Stealth Mode is bundled on the Hobby plan and above. You can test the exact call against any URL in the interactive playground before wiring it into your code.

The free tier gives you 100 screenshots a month with no credit card. That is enough to decide if the output beats whatever you are currently piping through Puppeteer.

Common questions about full page screenshots

Why is my full page screenshot cut off at the bottom?

Almost always one of two reasons. Either the page uses infinite scroll, in which case the document height keeps growing and the screenshot stops at whatever was rendered at capture time, or a parent element has overflow: hidden with a fixed height and the content inside is taller than the container. The first is solved by scrolling to the bottom before capturing (most screenshot APIs do this automatically with fullPage=true). The second is a CSS bug on the source page and has to be fixed there.

Can I take a full page screenshot of a Cloudflare protected site?

Yes, but not with vanilla headless Chrome. You need either a stealth plugin plus residential proxies, or an API that handles bot challenges for you. ScreenshotRender's Stealth Mode is bundled on the Hobby plan and above and covers Cloudflare, DataDome, and similar challenges without you setting any flags.

How do I screenshot a single page app or React site?

Single page apps usually finish loading after the network goes idle, because they swap content in based on user state or feature flags. The fix is to wait a fixed amount of time after the initial paint instead of waiting on networkidle0. With ScreenshotRender, add the wait parameter in milliseconds: https://screenshotrender.com/api/v1/screenshot?apiKey=YOUR_API_KEY&url=https://app.netlify.com&fullPage=true&wait=2000.

What is the difference between viewport and full page screenshot?

Viewport captures the slice currently visible in the browser window, typically 1280 by 720 or 1920 by 1080. Full page captures the entire scrollable document from top to bottom, regardless of window size. A landing page that scrolls four screens worth produces a viewport image at 720 pixels tall and a full page image closer to 2880 pixels tall.

Is there a free API for full page screenshots?

Yes. ScreenshotRender's free plan includes 100 screenshots per month with no credit card required, full page support, cookie banner removal, and ad blocking enabled by default. Stealth Mode for bot protected sites starts at the Hobby plan. See the pricing page for the full breakdown.

The honest verdict: devtools for personal use, headless Chromium if screenshots are core to your product and you want to own every layer, an API for everything else. The time saved on Chromium maintenance, font installation, and bot evasion alone usually pays for the API tier inside the first month.

Keep reading