How to Take Screenshots of Websites That Block Bots
A screenshot captures what a browser can render; it cannot grant access to a site that blocks bots. Here’s how to capture pages you can access, and what to do when access is denied.

A screenshot tool can capture a page after a browser has rendered it. It cannot grant access to a site that blocks the browser or automated request. If a bot check, CAPTCHA, or denial page appears instead of the page you need, the capture will show that response; changing screenshot software does not make access authorized.
If you can open the page in a permitted browser session, use a browser-native capture or browser automation such as Playwright. Pick a viewport, element, selected area, or full-page capture based on what you need to document. If access is denied, stop and ask the site owner for permission, an authorized copy, or a capture. Cloudflare’s Browser Run documentation states that its configurable user agent “does not bypass bot protection,” and that its requests are identified as bots. Cloudflare Browser Run screenshot documentation
1. First determine what is being blocked
“The website blocks bots” can describe two different problems. The distinction determines whether a screenshot workflow can help.

| What you see | What it means | Next step |
|---|---|---|
| The intended page opens in your ordinary browser. | You have a rendered page available to capture. | Use the browser’s capture feature or automation in that permitted session. |
| A bot check, CAPTCHA, access-denied message, or blank challenge appears before the page. | The requested content is not available to that request. | Do not treat a screenshot service as an access workaround. Ask the site owner for access or an authorized copy or capture. |
| The page is visible, but the screenshot command or browser capture is disabled. | Your browser, device, or organization may restrict screenshot capture. | Check whether the browser is managed and ask the administrator about the policy. |
A capture records rendered pixels; it does not authenticate a request or override a site’s access decision. No physical product is needed. Browser features and automation libraries handle the capture after the page is available.
2. Capture a page you can access with Playwright
Playwright supports viewport screenshots, full-page screenshots, and screenshots of a selected element. The example below opens a URL, waits for a specific page element, and saves a full-page PNG. It does not attempt to get around a denial or bot check. If the site presents one, the program should stop for you to handle access through an authorized route.

Install and run
- Install Node.js, then create a project directory.
- Install Playwright and its Chromium browser.
- Save the script below as
screenshot.mjsand setTARGET_URLto a page you are allowed to view. - Run it with Node.js. The image is saved as
page.pngin the current directory.
npm init -y
npm install playwright
npx playwright install chromium
// screenshot.mjs
import { chromium } from 'playwright';
const url = process.env.TARGET_URL;
if (!url) throw new Error('Set TARGET_URL to a page you are permitted to access.');
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
const response = await page.goto(url, {
waitUntil: 'domcontentloaded',
timeout: 30_000
});
console.log('HTTP status:', response?.status() ?? 'no main response');
console.log('Final URL:', page.url());
// Use a selector that identifies the content you need.
// Replace main with a stable selector from the permitted page.
await page.locator('main').waitFor({ state: 'visible', timeout: 10_000 });
await page.screenshot({ path: 'page.png', fullPage: true, animations: 'disabled' });
console.log('Saved page.png');
} finally {
await browser.close();
}
TARGET_URL='https://example.com' node screenshot.mjs
The URL in this command is a placeholder: substitute a page that you can access and are authorized to capture. Inspect the final URL, HTTP status, and visible content before treating the image as the intended page. A successful navigation can still lead to a challenge or an error page.
Choose the capture scope
- Viewport:
await page.screenshot({ path: 'viewport.png' });captures the visible browser viewport. Set viewport width and height when you need repeatable dimensions. - Full page:
await page.screenshot({ path: 'full.png', fullPage: true });captures the page’s full scrollable height. Very long pages can create large images and take longer to render. - Element:
await page.locator('article').screenshot({ path: 'article.png' });captures the matched element. Prefer a stable selector. If it matches nothing or several unintended elements, inspect the page and adjust it. - Clipped area: pass a
cliprectangle withx,y,width, andheighttopage.screenshot()when you need only a region of the viewport.
Playwright’s screenshot options also include image type (png, jpeg, or webp), JPEG/WebP quality, CSS-pixel or device-pixel scale, transparent background where supported, and a stylesheet for adjusting volatile page elements. JPEG does not support transparency. Device-pixel scale can produce larger images on high-density displays. See the Playwright screenshot guide and Page screenshot API for the current option list and details.
Wait for the right signal
domcontentloaded returns after the document is parsed, but client-side applications may still be rendering. Waiting for a meaningful element is usually more reliable than sleeping for an arbitrary number of seconds. Use a short fixed delay only when a known animation or delayed widget needs it. Waiting for all network activity to stop can hang or waste time on pages with analytics, long polling, or continuously loaded content. Playwright’s locator waits for the target state and times out if the element does not appear.
3. Capture manually when the page is already open
For a one-off capture, a browser’s built-in capture feature is often simpler than writing a script. Microsoft Edge documents Web Capture options for a selected area or a full page. Browser menus and labels may change, so consult the current Microsoft Edge help for your version. Playwright can capture viewport, element, or full scrollable page when the page is open in an automation-controlled browser. Playwright documents these capture scopes.
- Open the page through an access method the site permits.
- For a focused visual record, select the relevant area or element. Choose full page when content below the fold matters.
- Save the file with a useful name. When the capture needs context, record the source URL and capture date alongside it.
- Review the image before sharing. Redact account details or other sensitive information where appropriate.
If the site is not visible and instead shows a block, do not try to make a screenshot tool conceal or disguise its automated request. Ask the site owner or an authorized contact for a permitted way to obtain the material.
4. Check whether your organization manages screenshot access
Screenshot capture can be restricted by a managed browser or device, independently of whether the website itself is blocking you. Chrome Enterprise documents administrator-controlled screenshot-prevention settings for supported managed environments. If the capture command is disabled on a work or school device, check the browser’s managed status and ask your administrator whether a policy applies. Chrome Enterprise policy documentation
This is a control-context issue: a site block affects access to that site, while a browser or organization policy can affect whether capture is available at all. Follow your organization’s rules and request an approved exception or capture when needed.
5. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| The image shows a CAPTCHA or bot-check page. | The requested page was not served to the automated request. | Stop the automated capture. Request permission, an authorized copy, or a capture from the site owner. A user-agent option is not a bypass; Cloudflare explicitly documents this limit. |
| The image is blank or missing the main content. | The app rendered after navigation, the selector is wrong, or content requires an authorized interaction. | Check the final URL and page contents. Wait for a stable visible selector. If access is denied, use the site owner route instead of adding evasion behavior. |
Timeout 30000ms exceeded during navigation. |
The page is slow, the network is unavailable, or navigation did not finish before the timeout. | Check connectivity and the target URL. Consider a higher timeout for a legitimately slow page, while keeping a reasonable upper bound. Waiting for a specific content selector can be more useful than waiting for every request to finish. |
Timeout ... locator ... or “element not found.” |
The selector does not match, the element is hidden, or the expected page never loaded. | Inspect the rendered page, choose a stable selector, and verify that the expected content is present before capture. |
| The image is cut off or unexpectedly huge. | Viewport capture was used where full-page was needed, or the page has unusually tall content. | Choose the correct scope. For exceptionally long pages, capture a specific section or use multiple documented captures rather than relying on one unwieldy image. |
| The screenshot API or browser says capture is disabled. | A managed-browser, device, or organizational policy may apply. | Check with the administrator. Do not assume the website caused the restriction. |
| Text, animations, or images differ between runs. | Fonts, animation timing, lazy-loaded content, viewport, or the rendering environment changed. | Keep the browser and viewport consistent, wait for the content you need, disable finite animations for repeatability, and review the resulting image. |
6. Performance, reliability, and cost
For a single manual capture, the built-in browser feature has no automation setup. A local Playwright run adds browser installation and startup, but gives repeatable inputs and a script that can be reused. Capturing just an element generally produces a smaller artifact than a very long full-page image. Device-pixel output and high-resolution viewports can increase image dimensions and storage needs.
Reliability depends on more than the screenshot command: the requested page must be available, its content must finish rendering, and the selector or capture region must match the intended content. For repeatable records, keep the viewport and browser environment consistent, wait on a meaningful page condition, log the final URL and response status, and retain enough context to identify what the image represents. A screenshot is a visual record, not proof that the underlying content was available to every visitor.
Local browser automation has no per-shot ScreenshotNeo charge, but you maintain the runtime and browser. Hosted capture services may charge according to their own terms and results; inspect their current pricing and documentation. For a protected page, spending more on a screenshot service does not establish permission or guarantee access. ScreenshotNeo’s billing behavior and plan prices are described below.
7. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF. It is useful when the page is available for capture and you want an endpoint instead of maintaining a browser setup. It does not grant access to a page that blocks the request; use an authorized access route for denied pages. See the ScreenshotNeo API documentation.
For example, this cURL request saves a WebP capture:
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res); // Or write the response bytes with your Node.js file API.
In Node.js environments without Bun, save the response using Node’s file API:
import { writeFile } from 'node:fs/promises';
const bytes = new Uint8Array(await res.arrayBuffer());
await writeFile('shot.webp', bytes);
Replace the example URL with a page you are permitted to access. For custom output and capture behavior, the API supports full-page capture, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF options, custom CSS or JavaScript, click-before-capture, hide selectors, wait conditions, request blocking, headers, cookies, user agent, authorization, timezone and geolocation, transparent background, resizing, cache TTL, signed image links, async jobs with signed webhooks, bulk requests, usage API, and OpenAPI spec. The supplied product details also state that parameter names used by other screenshot APIs work for easier switching. Each of these options controls capture behavior; none is a promise of access through a site’s restrictions.
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and responses identify the result with X-Page-Verdict and X-Billed headers. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
The Free plan includes 1,000 shots per month with no card. Paid plans are Starter: $5 for 3,000, Growth: $15 for 15,000, Pro: $39 for 60,000, Scale: $99 for 250,000, and Business: $249 for 1,000,000. Yearly billing gives two months free; every feature is on every plan. Sign up for 1,000 free screenshots a month with no card.
8. Frequently asked questions
Can I take a screenshot if I can’t open the page?
A capture service can only record what its browser receives. If access is denied, request permission, an authorized copy, or a capture from the site owner.
Will changing the user agent fix a bot block?
Do not rely on it to bypass a protection. Cloudflare says its Browser Run user-agent setting does not bypass bot protection.
Should I use a viewport or full-page screenshot?
Use viewport for the visible section and full page when below-the-fold content matters. Choose an element or selected area for a focused record.
Why is screenshot capture disabled even though the page is visible?
Your browser, device, or organization may manage capture permissions. Ask the administrator whether a policy applies.
Does ScreenshotNeo remove the site’s bot protection?
No. Its cleanup removes specified overlays such as consent banners, newsletters, and chat widgets. It does not authorize access to a page that denies the request.

