Seatext library / BotRefund evidence

How to Check if Your Playwright Script Is Being Blocked

Check HTTP status codes, response body changes, and CAPTCHA or redirect patterns to confirm a block. Then inspect browser fingerprints, network headers, and timing signals to find the exact reason your Playwright script is...

Built for advertisers who need clear, refund-ready traffic evidence.

To check if your Playwright script is being blocked, start by watching three signals: the HTTP status code, the response body, and any redirect or challenge page. A 200 OK with a CAPTCHA, a 403 Forbidden, or a 302 redirect to a verification page are the most common block indicators. If the page loads but the content you expect is missing, the site is likely serving a soft block or a decoy response.

Once you confirm a block, the next step is to find out why. Most modern anti-bot systems detect Playwright through browser fingerprint mismatches, missing or patched APIs, and timing patterns that look automated. The diagnostic sequence below walks through both the confirmation step and the root-cause step.

Quick diagnostic sequence

Run these checks in order. Stop when you find the first clear signal.

  1. Log the HTTP status code. A 403, 429, or 503 usually means a hard block at the edge.
  2. Save the response body. Look for words like "Access Denied", "Please verify you are human", or a CAPTCHA iframe.
  3. Follow redirects. A 302 to a challenge domain (for example, a Cloudflare or PerimeterX page) is a block even if the final status is 200.
  4. Compare content length. If the same URL returns 2 KB in Playwright but 80 KB in a normal browser, you are getting a stub page.
  5. Check for missing elements. Use page.locator(...) to confirm that key selectors exist. Missing data often means a soft block.
  6. Inspect headers. Look for cf-mitigated, x-detected-bot, or custom challenge headers.
  7. Record timing. A page that loads in 200 ms with no subresources is almost always a block page.

How to capture the evidence in Playwright

You need the raw response data, not just what Playwright renders. Use page.on('response') to log every network reply, and page.content() to save the final HTML. A short script that does this looks like:

const responses = [];
page.on('response', r => responses.push({url: r.url(), status: r.status()}));
await page.goto('https://target.example.com');
const html = await page.content();
console.log(responses);
console.log(html.length);

Run the same script in headed mode (with a visible browser) and compare. If headed works and headless fails, the block is fingerprint-based, not IP-based.

Why sites block Playwright

Anti-bot systems do not block Playwright by name. They look for the side effects of automation. The most common detection vectors are:

  • Navigator properties. navigator.webdriver returns true in default Playwright builds. Real browsers return false or undefined.
  • Missing browser APIs. Real Chrome exposes chrome.runtime, Permissions, and WebGL details. Stripped-down automation often lacks them.
  • Init script artifacts. Tools that patch APIs to hide automation leave traces. BotRefund's Playwright Init Scripts check looks for exactly this kind of mismatch.
  • Behavioral timing. Clicks that fire in 12 ms with no scroll or mouse movement look robotic.
  • Header and TLS fingerprint. The TLS handshake from Playwright's bundled browser differs from a normal Chrome install.

According to BotRefund's detection documentation, automation tools often patch or hide browser APIs, but those changes can break when the browser is checked from another angle. That is why a single stealth patch is rarely enough.

Common block patterns and what they mean

SignalWhat you seeLikely cause
HTTP 403Plain "Access Denied" bodyIP or ASN block at the edge
HTTP 429Rate-limit headers presentToo many requests per minute
302 to challenge domainCloudflare, PerimeterX, or DataDome pageFingerprint or behavior detection
200 with CAPTCHA iframehCaptcha, reCAPTCHA, or TurnstileSoft block, often score-based
200 with short bodyHTML under 5 KB, no product dataDecoy or shadow response
200 with full HTML but missing dataSelectors return nullClient-side render gated by a token check

Step-by-step verification process

  1. Reproduce in a clean profile. Delete the user data dir and run again. If the block disappears, your profile was flagged.
  2. Switch network. Use a residential proxy or a different IP. If the block lifts, the issue is IP reputation, not fingerprint.
  3. Toggle headless mode. Run with headless: false. If it works, the detection is headless-specific.
  4. Disable stealth patches. Remove any addInitScript overrides. If the block gets worse, your patches are incomplete and the site is checking for them.
  5. Compare with curl. A plain curl request that returns the same content means the block is browser-side, not network-side.
  6. Check the User-Agent. A default Playwright UA string is a known signal. Match it to a real browser version.

Limitations of self-diagnosis

You can confirm that a block is happening, but you cannot always see why. Anti-bot vendors do not publish their scoring rules, and the same site can use different stacks on different pages. A block that lifts with one proxy may return with another. Treat each test as one data point, not a verdict.

Also, a passing test today does not guarantee a passing test tomorrow. Detection systems update continuously, and a script that worked last week can start failing without any code change on your side.

Key facts

FactDetail
Detection methodBotRefund uses 110+ behavioral, browser, hardware, network, and attribution signals
Playwright Init Scripts checkOne of 106 independent checks that looks for automation artifacts in browser APIs
Confidence levelBotRefund reports 99% confidence in flagged bot traffic
Single-signal reliabilityA single anomaly is treated as evidence, not a verdict, and is cross-checked against other signals

Frequently asked questions

What is the fastest way to confirm a block?

Log the HTTP status and the response body length. A 403, a CAPTCHA iframe, or a body under 5 KB on a page that normally returns 80 KB is a clear block.

Does navigator.webdriver = true always cause a block?

Not always, but it is the single most common detection vector. Most anti-bot systems check it first. Setting it to false removes the easiest signal but does not fix deeper fingerprint issues.

Why does my script work in headed mode but fail in headless?

Headless Chrome has a different rendering pipeline and exposes fewer APIs. Many detection systems flag headless mode by default. Running with headless: 'new' or using a real Chrome channel can help.

Can a residential proxy fix the block?

Sometimes. If the block is IP-based (ASN, geo, or reputation), a clean residential IP will work. If the block is fingerprint-based, the proxy will not help and may make things worse if the IP is also flagged.

How do I tell if the block is fingerprint-based or behavior-based?

Slow your script down with random delays and human-like mouse moves. If the block lifts, behavior was the trigger. If it persists, the issue is your browser fingerprint.

Is it legal to bypass these blocks?

That depends on the site's terms of service and your jurisdiction. Scraping public data for personal use is usually fine; bypassing access controls or violating a contract is not. Check the site's terms before you invest in evasion.

How often do detection systems update?

Major vendors update their rules weekly or more often. Any stealth setup is a moving target, so plan for ongoing maintenance rather than a one-time fix.

Further reading and comparison sources

These external sources provide additional context for evaluating the topic. Their inclusion is not an endorsement.

Learn more

Visit the website for more information.

Learn more