Skip to main content

IntelliScraper

A powerful anti-bot detection async web scraping library built on Playwright. Designed for scraping protected sites job platforms, social networks, e-commerce dashboardsthat require authentication and sophisticated anti-detection.

PyPI Version Documentation Python Version License Status


📖 Documentation

For detailed guides, tutorials, and full API reference, please visit our official documentation.


✨ Features

Feature Description
🔐 Session Management Capture and reuse authentication sessions (cookies, localStorage, fingerprints)
🖥️ Local Browser Mode Connect to your running Chrome via CDP all existing logins available instantly
🤖 Managed Browser Mode Launch headless Chromium with fingerprint spoofing and anti-detection
⏱️ Rate Limiting Token-bucket rate limiter shared across all concurrent pages
📦 Batch Scraping batch_scrape() for processing hundreds of URLs with concurrency + rate control
🛡️ Anti-Detection WebDriver flag removal, plugin spoofing, WebGL masking, human-like scrolling
🌐 Proxy Support Bright Data integration and custom proxy providers
📝 Extensible Parsers HTML → text, links, Markdown. Extend for site-specific parsing
⚡ Fully Async Built with async/await for maximum concurrency

🚀 Quick Start

Installation

# Install the package
pip install intelliscraper-core

# Install Playwright browser (Chromium)
playwright install chromium

[!NOTE] Playwright requires browser binaries installed separately. The command above installs Chromium.


⚡ Basic Scraping

import asyncio
from intelliscraper import AsyncScraper, ScrapStatus

async def main():
    async with AsyncScraper() as scraper:
        response = await scraper.scrape("https://example.com")

        if response.status == ScrapStatus.SUCCESS:
            print(f"HTTP {response.http_status_code}")
            print(f"Time: {response.elapsed_time:.2f}s")
            print(response.scrap_html_content[:500])

asyncio.run(main())

📦 Batch Scraping with Rate Limiting

Scrape many URLs with automatic rate limiting and concurrency control:

import asyncio
from intelliscraper import AsyncScraper, ScrapStatus

async def main():
    async with AsyncScraper(
        max_concurrent_pages=4,
        max_requests_per_minute=900,  # 15 requests/sec across all pages
    ) as scraper:
        urls = [f"https://example.com/page/{i}" for i in range(100)]
        results = await scraper.batch_scrape(urls)

        for result in results:
            print(
                f"{result.scrape_request.url} → "
                f"{result.status.value} "
                f"(HTTP {result.http_status_code}, "
                f"{result.elapsed_time:.2f}s)"
            )

asyncio.run(main())

[!IMPORTANT] The rate limit is shared across all concurrent pages. With max_concurrent_pages=4 and max_requests_per_minute=900, the 4 pages share a combined budget of 15 requests/second not 15/sec each.


🖥️ Local Browser Mode (CDP)

Connect to your running Chrome instance to reuse existing logins (LinkedIn, Gmail, etc.).

Setup (one-time)

# 1. Create the debug profile
make chrome-debug-profile

# 2. Open Chrome with the debug profile and log into your target sites
make chrome-debug-login URL=https://www.linkedin.com

# 3. Log in to the site in the browser that opens
# 4. Close Chrome when done

[!WARNING] The debug profile (~/.config/google-chrome-debug) is separate from your default Chrome profile. You must log into target sites in this profile before scraping.

Usage

import asyncio
from intelliscraper import AsyncScraper, ScrapStatus

async def main():
    async with AsyncScraper(
        use_local_browser=True,
        headless=False,
    ) as scraper:
        response = await scraper.scrape(
            "https://www.linkedin.com/jobs/collections/recommended/"
        )

        if response.status == ScrapStatus.SUCCESS:
            print(f"HTTP {response.http_status_code}")
            print(f"Session: {response.session_id}")
            print(f"Mode: {response.browser_mode}")

asyncio.run(main())

How It Works

  1. IntelliScraper checks if Chrome is running with --remote-debugging-port=9222.
  2. If not, it auto-launches Chrome using the debug profile.
  3. Connects via CDP and reuses the existing browser context (all cookies and logins preserved).
  4. Only the pages opened by IntelliScraper are closed on exit your Chrome session stays running.

🔐 Session-Based Scraping (Managed Browser)

For sites that require authentication without using your local Chrome:

1. Capture a Session

intelliscraper-session \
    --url "https://example.com" \
    --site "example" \
    --output "./example_session.json"

This opens a browser log in, then press Enter. Session data (cookies, localStorage, fingerprint) is saved to JSON.

2. Use the Session

import asyncio
import json
from intelliscraper import AsyncScraper, Session, ScrapStatus

async def main():
    with open("example_session.json") as f:
        session = Session(**json.load(f))

    async with AsyncScraper(session_data=session) as scraper:
        response = await scraper.scrape("https://example.com/dashboard")

        if response.status == ScrapStatus.SUCCESS:
            print(f"Session: {response.session_id}")
            print(response.scrap_html_content[:500])

asyncio.run(main())

📝 HTML Parsing

Default Parser

from intelliscraper.parsers import HTMLParser

parser = HTMLParser(url="https://example.com", html=html_content)
print(parser.text)               # Plain text
print(parser.links)              # List of absolute URLs
print(parser.navigable_links)    # Classified internal/external links
print(parser.markdown)           # Full Markdown
print(parser.markdown_for_llm)   # Cleaned Markdown (for LLM input)

Custom Parsers

Extend HTMLParser for site-specific extraction:

from functools import cached_property
from intelliscraper.parsers import HTMLParser

class MyJobParser(HTMLParser):
    """Custom parser for a job listing site."""

    @cached_property
    def job_title(self) -> str | None:
        tag = self.soup.select_one("h1.job-title")
        return tag.get_text(strip=True) if tag else None

    @cached_property
    def company(self) -> str | None:
        tag = self.soup.select_one("span.company-name")
        return tag.get_text(strip=True) if tag else None

🌐 Proxy Support

Proxy is used in managed browser mode only (not with local browser / CDP).

Bright Data Proxy

import asyncio
from intelliscraper import AsyncScraper, BrightDataProxy, ScrapStatus

async def main():
    proxy = BrightDataProxy(
        host="brd.superproxy.io",
        port=22225,
        username="your-username",
        password="your-password",
    )

    async with AsyncScraper(proxy=proxy) as scraper:
        response = await scraper.scrape("https://example.com")
        print(f"Status: {response.status.value}")

asyncio.run(main())

Custom Proxy Provider

from intelliscraper import ProxyProvider, Proxy

class MyProxy(ProxyProvider):
    def get_proxy(self) -> Proxy:
        return Proxy(
            server="http://my-proxy.com:8080",
            username="user",
            password="pass",
        )

[!NOTE] All pages within a single AsyncScraper instance share the same proxy. For different proxies, create separate AsyncScraper instances.


📊 Response Model

Every scrape() and batch_scrape() call returns a ScrapeResponse with:

Field Type Description
scrape_request ScrapeRequest Original request parameters
status ScrapStatus Outcome: SUCCESS, PARTIAL_SUCCESS, FAILED, RATE_LIMITED, BLOCKED, TIMEOUT
http_status_code int | None Actual HTTP status from the server (200, 403, 429, etc.)
elapsed_time float | None Total scrape duration in seconds
scrap_html_content str | None Raw HTML from the page
error_msg str | None Error message on failure
session_id str | None Session site identifier used
browser_mode str | None "local_browser" or "managed_browser"

🏗️ Architecture

intelliscraper/
├── scraper.py              # AsyncScraper main orchestrator
├── rate_limiter.py         # Token-bucket rate limiter
├── enums.py                # ScrapStatus, BrowsingMode, HTMLParserType
├── exception.py            # Custom exceptions
├── utils.py                # URL normalisation utilities
│
├── browser/                # Browser backend strategy pattern
│   ├── backend.py          # BrowserBackend ABC
│   ├── local.py            # LocalBrowserBackend (CDP)
│   └── managed.py          # ManagedBrowserBackend (Playwright)
│
├── parsers/                # Content parsers
│   ├── base_parser.py      # BaseParser ABC
│   └── html_parser.py      # HTMLParser (general purpose)
│
├── common/
│   ├── constants.py        # Browser fingerprints, launch options
│   └── models.py           # Pydantic models (Proxy, Session, etc.)
│
├── proxy/
│   ├── base.py             # ProxyProvider ABC
│   └── brightdata.py       # BrightDataProxy
│
└── scripts/
    └── get_session_data.py # CLI session capture tool

📋 Requirements

  • Python 3.12+
  • Playwright + Chromium
  • Compatible with Linux, macOS, and Windows

🛠️ Development

# Install dependencies
make install

# Install Playwright Chromium
make playwright-chromium

# Run tests
make test

# Format code
make format

Chrome Debug Profile Commands

make chrome-debug-profile                        # Create debug profile
make chrome-debug-login URL=https://linkedin.com  # Log in to a site
make chrome-debug-stop                            # Stop Chrome debug

🗺️ Roadmap

  • ✅ Async scraping with concurrent pages
  • ✅ Local browser mode (CDP)
  • ✅ Session management CLI
  • ✅ Proxy integration (Bright Data)
  • ✅ HTML parsing and Markdown generation
  • ✅ Anti-detection mechanisms
  • ✅ Rate limiting (token bucket)
  • ✅ Batch scraping API
  • ✅ Extensible parser architecture
  • 🔄 Proxy rotation
  • 🔄 Distributed crawler mode
  • 🔄 AI-based content extraction

📄 License

Licensed under the MIT License.


📧 Support

For help, issues, or contributions visit the GitHub Issues page.

Release files for intelliscraper-core 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for intelliscraper-core 0.2.0
File Size Uploaded
intelliscraper_core-0.2.0.tar.gz 87.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for intelliscraper-core 0.2.0
File Interpreter ABI Platform
intelliscraper_core-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 129.9 kB

Release files / intelliscraper_core-0.2.0.tar.gz

Download URL intelliscraper_core-0.2.0.tar.gz
Size 87.8 kB
Tags Source
SHA-256 checksum
How to use checksums
3858f831e5ac53741d025581169f3493f8c193dbfaa50c16bab2333239975617
BLAKE2b-256 checksum
How to use checksums
a06e8949d839bd9c1db31d4a656f8aa0ca6335fd490d463f46f474060a5fb91c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.12

Release files / intelliscraper_core-0.2.0-py3-none-any.whl

Download URL intelliscraper_core-0.2.0-py3-none-any.whl
Size 42.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dfd7fe22d0a695d9ec3fb866e603bdcc5300d4f20bc8c79b1ae389631f0b64b7
BLAKE2b-256 checksum
How to use checksums
3896be64e27ddb37d60d068c85bb01c3e54fea3f2fad1150de53caa825e84a6a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.12

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page