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.
- Log the HTTP status code. A 403, 429, or 503 usually means a hard block at the edge.
- Save the response body. Look for words like "Access Denied", "Please verify you are human", or a CAPTCHA iframe.
- 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.
- 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.
- Check for missing elements. Use
page.locator(...)to confirm that key selectors exist. Missing data often means a soft block. - Inspect headers. Look for
cf-mitigated,x-detected-bot, or custom challenge headers. - 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.webdriverreturnstruein default Playwright builds. Real browsers returnfalseorundefined. - 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
| Signal | What you see | Likely cause |
|---|---|---|
| HTTP 403 | Plain "Access Denied" body | IP or ASN block at the edge |
| HTTP 429 | Rate-limit headers present | Too many requests per minute |
| 302 to challenge domain | Cloudflare, PerimeterX, or DataDome page | Fingerprint or behavior detection |
| 200 with CAPTCHA iframe | hCaptcha, reCAPTCHA, or Turnstile | Soft block, often score-based |
| 200 with short body | HTML under 5 KB, no product data | Decoy or shadow response |
| 200 with full HTML but missing data | Selectors return null | Client-side render gated by a token check |
Step-by-step verification process
- Reproduce in a clean profile. Delete the user data dir and run again. If the block disappears, your profile was flagged.
- Switch network. Use a residential proxy or a different IP. If the block lifts, the issue is IP reputation, not fingerprint.
- Toggle headless mode. Run with
headless: false. If it works, the detection is headless-specific. - Disable stealth patches. Remove any
addInitScriptoverrides. If the block gets worse, your patches are incomplete and the site is checking for them. - Compare with curl. A plain
curlrequest that returns the same content means the block is browser-side, not network-side. - 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
| Fact | Detail |
|---|---|
| Detection method | BotRefund uses 110+ behavioral, browser, hardware, network, and attribution signals |
| Playwright Init Scripts check | One of 106 independent checks that looks for automation artifacts in browser APIs |
| Confidence level | BotRefund reports 99% confidence in flagged bot traffic |
| Single-signal reliability | A 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.