ScreenshotNeo

BlogHow-to

How to Take Screenshots of CAPTCHA-Protected Pages

Capture a CAPTCHA page as it appears in your browser, choose the right screenshot scope, and troubleshoot missing challenges without trying to solve or bypass them.

By the ScreenshotNeo team4 October 20268 min read

To screenshot a CAPTCHA-protected page, open it in a browser, wait until the state you need to document is visible, then capture the viewport, a specific element, or the full page. A screenshot records what the browser rendered in that session at that moment. It does not solve, pass, or submit a CAPTCHA.

For an authorized capture, Playwright can save PNG, JPEG, or WebP screenshots. Use viewport capture for the current screen, element capture for a widget, and full-page capture when content below the fold matters. If you own the integration and need repeatable tests, use Google’s test configuration guidance rather than treating a production challenge as a test fixture.

Choose what to capture

Scope Use it for Playwright option
Viewport The visible challenge and nearby page context Default page screenshot
Element A particular CAPTCHA widget or error message locator.screenshot()
Full page Page content below the current viewport fullPage: true

Playwright documents viewport, element, and full-page screenshots, along with output format and scale settings. Its guidance treats screenshots as a way to visually verify a page or document a bug; when the goal is page structure or readable text, use an accessibility snapshot instead. An element screenshot and fullPage are separate capture choices: Playwright does not combine full-page capture with an element target. Playwright screenshot documentation

Capture a CAPTCHA page with Playwright

Use this workflow only for pages you are authorized to access and document. It opens the page normally and captures its rendered state; it does not interact with the challenge.

  1. Install Playwright and its Chromium browser.
  2. Save the script below as capture.mjs.
  3. Set TARGET_URL to the page you are authorized to capture, then run the script.
npm install playwright
npx playwright install chromium
import { chromium } from 'playwright';

const url = process.env.TARGET_URL;
if (!url) throw new Error('Set TARGET_URL to the page to capture');

const browser = await chromium.launch({ headless: true });
try {
  const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } });
  await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 45000 });
  // Allow client-side rendering a short interval; adjust for your own page.
  await page.waitForTimeout(1500);
  await page.screenshot({ path: 'captcha-page.png', type: 'png' });
} finally {
  await browser.close();
}
TARGET_URL='https://example.com/protected-page' node capture.mjs

Replace the example URL with your permitted target. domcontentloaded means the initial document has been parsed; a challenge or widget may render later through client-side code. The short delay is a simple starting point, not a guarantee. For a site you control, prefer waiting for a stable, known element that signals the state you intend to capture.

Capture one element

Inspect your own page to identify a stable selector for the widget or relevant message. The selector depends on the page; do not assume third-party CAPTCHA markup uses a particular selector.

const widget = page.locator('[data-testid="captcha-widget"]');
await widget.waitFor({ state: 'visible', timeout: 15000 });
await widget.screenshot({ path: 'captcha-widget.png', type: 'png' });

Capture the full page

await page.screenshot({ path: 'captcha-full-page.png', fullPage: true, type: 'png' });

Full-page capture can make a small challenge appear tiny when viewed at fit-to-window scale. Keep a viewport or element capture as well if the challenge itself needs to be legible.

Choose format and scale

PNG is a sensible default for crisp interface text and visual evidence. JPEG can be useful where smaller photographic output matters; WebP is also supported by Playwright. The scale option can use CSS-pixel sizing or device-pixel sizing. Device-pixel scale can produce more detail at higher dimensions; CSS scale keeps output closer to CSS pixel dimensions. Consider the image’s final viewing size before choosing.

await page.screenshot({ path: 'captcha.png', type: 'png', scale: 'css' });
await page.screenshot({ path: 'captcha-retina.png', type: 'png', scale: 'device' });
await page.screenshot({ path: 'captcha.webp', type: 'webp' });

See the Playwright screenshot API guidance for supported screenshot options and details.

Make the capture useful as evidence

  • Capture the browser state after the page has rendered the condition under discussion.
  • Include enough surrounding page context to identify where the challenge appeared.
  • Record the capture date and time, browser, page URL, and relevant test context alongside the image when those details matter to the report. This is practical documentation advice, not a requirement imposed by Playwright.
  • Keep the original image when you need an unaltered visual record. If you annotate a copy for discussion, label it as annotated.
  • A screenshot only shows the displayed state. It does not establish whether verification succeeded, what server-side decision was made, or whether a user completed a challenge.

Google describes reCAPTCHA as a service intended to help distinguish people from bots. Its user-facing flow may show a checkbox and sometimes an additional challenge. Google reCAPTCHA Help

Why the CAPTCHA may be missing

A missing visible challenge does not necessarily mean the integration failed. Google’s documentation distinguishes score-based keys, which do not display a checkbox or challenge, from checkbox, policy-based challenge, and invisible integrations that may display challenges. A screenshot records only the state shown in the particular session. Google’s reCAPTCHA version comparison

  • The integration does not show a visible challenge in this state. Check which reCAPTCHA type the site uses and what state the page is expected to render.
  • The capture happened before the widget appeared. Wait for a known visible element on a site you own, or use a suitable delay as a temporary measure.
  • The widget is outside the captured viewport. Scroll it into view or capture the element. Use full-page capture only when below-the-fold context is needed.
  • The screenshot is too small to inspect. Capture the widget itself or use device scale for additional pixel detail.
  • You saw an automated-query warning rather than an ordinary challenge. Google provides a separate diagnostic path for that warning. Its help says that if a normal CAPTCHA appears on its CAPTCHA page, the originating site may have a configuration issue and suggests notifying that site. Google Search automated-query troubleshooting

For site owners: make CAPTCHA tests reproducible

Use the CAPTCHA provider’s documented test configuration for your integration. Google’s reCAPTCHA FAQ says v3 should use a separate testing key. For v2, Google provides test keys that always produce “No CAPTCHA” and pass verification, and warns that those keys are for testing rather than production traffic. Do not rely on a production challenge appearing identically on every run. Google reCAPTCHA FAQ

Keep test keys and test configuration in the test environment. Assert the page state your test is meant to cover, and capture a screenshot at the point where that state is visible. The screenshot helps diagnose visual regressions; the integration’s verification result must be checked through the application’s own test assertions.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its one-call API can return a screenshot or PDF; see the ScreenshotNeo API documentation. For a screenshot of a permitted page, the basic request is:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/protected-page -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.com/protected-page"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://example.com/protected-page'
});
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);

Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot, and each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed; response headers report the page verdict and billing status. This does not solve or pass a CAPTCHA. An MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card.

Performance, reliability, and cost

With a local browser, capture time depends on navigation, page rendering, and the wait condition you choose. Long fixed delays can make a script slow, while short delays can capture an incomplete state. Prefer a meaningful visibility condition when you control the page. Full-page and device-scale captures can create larger image files than a viewport capture at CSS scale; select scope and scale based on what must remain readable.

For repeatable reports, retain the URL and capture context with the artifact, use explicit navigation timeouts, and close the browser in a finally block so a failed navigation does not leave the process running. Treat a navigation timeout and a completed screenshot as different outcomes: do not silently present an incomplete capture as proof that the challenge was absent.

Playwright is a browser automation library, so a local workflow uses your own browser runtime and compute resources. ScreenshotNeo is usage-based by plan: Free is 1,000 shots/month, Starter is $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; all listed features are on every plan. Clean shots are billed, while the listed failed or non-page outcomes and cache hits cost nothing. These product facts do not imply a guarantee that a CAPTCHA challenge will appear or be captured in every session.

Troubleshooting

Symptom Likely cause What to do
Screenshot is blank or incomplete Navigation or client-side rendering had not reached the intended state Check that navigation completed, then wait for a known visible state on a page you control. Do not treat a blank capture as a successful verification.
Element locator times out The selector is wrong, the element has not appeared, or it is not visible in this state Inspect your own page’s markup and use a stable selector; wait for visibility only when that state is expected.
Challenge is not shown The integration or session may not render a visible challenge Confirm the reCAPTCHA type and expected behavior. For owned test integrations, follow Google’s testing guidance.
Challenge is unreadably small Full-page dimensions or CSS-pixel output reduced the displayed size Capture the target element or use device scale, then inspect at native size.
Navigation timeout The page did not reach the selected load condition within the timeout Check network access and the destination’s behavior; choose a suitable timeout and a later explicit readiness condition if the page legitimately renders after initial document load.
Automated-query warning appears This is a separate Google diagnostic flow, not necessarily a normal CAPTCHA widget Follow Google’s automated-query help and notify the originating site if the diagnostic indicates its configuration may be responsible.

FAQ

Does a screenshot prove that I passed the CAPTCHA?

No. It shows the page’s visible state at capture time, not the result of server-side verification.

Should I use a screenshot or an accessibility snapshot?

Use a screenshot to document visual appearance. Use an accessibility snapshot when you need page structure and text.

Can I make a CAPTCHA appear every time in my own test?

Use the provider’s documented test configuration. Google’s reCAPTCHA guidance describes separate v3 testing keys and v2 test keys for test traffic.

Can I capture a widget and the whole page in one Playwright screenshot?

Playwright’s full-page capture and element-target capture are different scopes. Save separate captures when you need both views.

Sources