Skip to content

Instantly share code, notes, and snippets.

@usametov
Created March 12, 2025 03:57
Show Gist options
  • Save usametov/efb9877239ce645bf2b458555b0e23d7 to your computer and use it in GitHub Desktop.
Save usametov/efb9877239ce645bf2b458555b0e23d7 to your computer and use it in GitHub Desktop.
how to avoid being blocked

When scraping websites using Playwright in headless mode, you might get blocked due to anti-bot measures implemented by the target website. These measures often detect automated browsers and block them to prevent scraping. Below are several strategies to help you avoid being blocked, along with implementation tips using Playwright in Python or JavaScript.


Why You're Getting Blocked

Websites use various techniques to detect headless browsers, such as:

  1. User-Agent Detection: Your browser's user-agent might indicate a headless browser.
  2. Browser Fingerprinting: Websites analyze browser properties (e.g., screen resolution, WebGL, plugins) to detect automation.
  3. Behavior Analysis: Websites may track mouse movements, click patterns, or other human-like behavior.
  4. IP Blocking: Frequent requests from the same IP can trigger rate-limiting or blocking.
  5. CAPTCHAs: Some websites present CAPTCHAs to verify human users.

Solutions to Avoid Being Blocked

1. Use a Realistic User-Agent

  • Websites often block requests with user-agents that indicate a headless browser (e.g., "HeadlessChrome").
  • Solution: Set a user-agent that mimics a real browser.

Python Example:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    context = browser.new_context(
        user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
    )
    page = context.new_page()
    page.goto("https://example.com")
    print(page.content())
    browser.close()

JavaScript Example:

const { chromium } = require('playwright');

(async () => {
    const browser = await chromium.launch({ headless: true });
    const context = await browser.newContext({
        userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36'
    });
    const page = await context.newPage();
    await page.goto('https://example.com');
    console.log(await page.content());
    await browser.close();
})();

2. Set Viewport and Device Emulation

  • Websites may block headless browsers based on default viewport sizes or missing device properties.
  • Solution: Emulate a real device's viewport and screen resolution.

Python Example:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    context = browser.new_context(
        viewport={'width': 1920, 'height': 1080},
        screen={'width': 1920, 'height': 1080},
        device_scale_factor=1,
    )
    page = context.new_page()
    page.goto("https://example.com")
    print(page.content())
    browser.close()

3. Evade Browser Fingerprinting

  • Websites use JavaScript to detect browser properties (e.g., navigator.webdriver, WebGL, or canvas fingerprinting) to identify headless browsers.
  • Solution: Use Playwright's built-in evasions or a stealth plugin.

Option A: Use Playwright's Built-in Features

  • Playwright has built-in mechanisms to evade detection, such as disabling the navigator.webdriver flag.

Python Example:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    context = browser.new_context(
        bypass_csp=True,  # Bypasses Content Security Policy
        ignore_https_errors=True,  # Ignores HTTPS errors
        java_script_enabled=True,
        # Disable webdriver flag
        extra_http_headers={"Accept-Language": "en-US,en;q=0.9"}
    )
    page = context.new_page()
    # Disable webdriver detection
    page.evaluate("() => { Object.defineProperty(navigator, 'webdriver', { get: () => false }); }")
    page.goto("https://example.com")
    print(page.content())
    browser.close()

Option B: Use Playwright Stealth Plugin

  • For more robust evasion, consider using a third-party plugin like playwright-stealth (Python) or playwright-extra (JavaScript).

Python Example with playwright-stealth:

from playwright.sync_api import sync_playwright
from playwright_stealth import stealth_sync

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    context = browser.new_context()
    page = context.new_page()
    stealth_sync(page)  # Apply stealth settings
    page.goto("https://example.com")
    print(page.content())
    browser.close()

To install playwright-stealth:

pip install playwright-stealth

4. Use Proxies to Rotate IPs

  • Websites may block your IP if you send too many requests from the same address.
  • Solution: Use a proxy service to rotate IPs. Services like Bright Data, Smartproxy, or Oxylabs provide rotating residential proxies.

Python Example with Proxies:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(
        headless=True,
        proxy={
            "server": "http://proxy.example.com:8080",
            "username": "your_username",
            "password": "your_password"
        }
    )
    page = browser.new_page()
    page.goto("https://example.com")
    print(page.content())
    browser.close()
  • Free Proxy Alternative: You can use free proxy lists, but they are often unreliable and slow. Paid proxy services are recommended for production scraping.

5. Mimic Human Behavior

  • Websites may detect automated behavior if you navigate too quickly or don't interact like a human.
  • Solution: Add delays, random mouse movements, and scrolling.

Python Example:

from playwright.sync_api import sync_playwright
import time
import random

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    page.goto("https://example.com")
    
    # Add random delay
    time.sleep(random.uniform(1, 3))
    
    # Simulate scrolling
    page.evaluate("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(random.uniform(0.5, 1.5))
    
    # Simulate mouse movement
    page.mouse.move(random.randint(100, 500), random.randint(100, 500))
    
    print(page.content())
    browser.close()

6. Handle CAPTCHAs

  • If the website uses CAPTCHAs, you may need to solve them manually or use a CAPTCHA-solving service.
  • Solution: Use services like 2Captcha, Anti-Captcha, or DeathByCaptcha to solve CAPTCHAs automatically.

Python Example with 2Captcha:

from twocaptcha import TwoCaptcha
from playwright.sync_api import sync_playwright

solver = TwoCaptcha('YOUR_2CAPTCHA_API_KEY')

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    page.goto("https://example.com")
    
    # Check if CAPTCHA is present
    if page.query_selector("div.g-recaptcha"):
        site_key = page.get_attribute("div.g-recaptcha", "data-sitekey")
        captcha_response = solver.recaptcha(sitekey=site_key, url="https://example.com")
        page.evaluate(f"document.getElementById('g-recaptcha-response').innerHTML = '{captcha_response['code']}';")
        page.click("button[type='submit']")  # Submit CAPTCHA form
    
    print(page.content())
    browser.close()

To install 2captcha:

pip install 2captcha

7. Rate Limiting and Throttling

  • Sending too many requests in a short time can trigger rate-limiting.
  • Solution: Add delays between requests and limit the number of concurrent requests.

Python Example:

from playwright.sync_api import sync_playwright
import time

urls = ["https://example.com/page1", "https://example.com/page2", "https://example.com/page3"]

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    
    for url in urls:
        page.goto(url)
        print(page.content())
        time.sleep(random.uniform(5, 10))  # Random delay between requests
    
    browser.close()

8. Use Headful Mode for Debugging

  • If you're still getting blocked, try running Playwright in headful mode (non-headless) to observe the browser behavior and identify what triggers the block.
  • Solution: Set headless=False during development.

Python Example:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False, slow_mo=100)  # Slow down actions for visibility
    page = browser.new_page()
    page.goto("https://example.com")
    print(page.content())
    browser.close()

9. Check Website's Terms of Service

  • Some websites explicitly prohibit scraping in their Terms of Service (ToS). Violating these terms could lead to legal consequences.
  • Solution: Review the website's ToS and robots.txt file to ensure scraping is allowed. If not, consider using an official API if available.

Python Example to Check robots.txt:

import requests
from urllib.parse import urljoin

base_url = "https://example.com"
robots_url = urljoin(base_url, "/robots.txt")
response = requests.get(robots_url)
print(response.text)

10. Use a Cloud-Based Scraping Service

  • If the website's anti-bot measures are too strict, consider using a cloud-based scraping service that handles all the complexities for you, such as ScrapingBee, Zyte (formerly Scrapinghub), or Apify.

Recommended Workflow

  1. Start with basic Playwright setup and test in headful mode.
  2. Add a realistic user-agent and viewport settings.
  3. Use playwright-stealth or built-in evasions to avoid fingerprinting.
  4. Implement proxies if you need to rotate IPs.
  5. Add human-like behavior (delays, scrolling, mouse movements).
  6. Handle CAPTCHAs if necessary.
  7. Test in headless mode and monitor for blocks.
  8. If all else fails, consider a cloud-based scraping service.

Important Notes

  • Ethical Scraping: Always respect the website's ToS and robots.txt. Avoid overloading servers with too many requests.
  • Legal Considerations: Web scraping laws vary by jurisdiction. Consult a legal expert if you're unsure about the legality of scraping a specific website.
  • Dynamic Content: If the website uses JavaScript to load content, ensure you wait for the content to load using Playwright's page.wait_for_selector() or page.wait_for_timeout().

If you provide more details about the specific website you're scraping or the error messages you're encountering, I can tailor the solution further. Let me know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment