Skip to main content

An adaptive web scraping framework — fast, stealthy, and self-healing

Project description

WhisperCrawler

Adaptive web scraping — fast, stealthy, and self-healing.

Python 3.10+ License Build Coverage

What it does

  • Bypasses advanced bot protection using stealthy, heavily-patched headless browsers.
  • Rapidly extracts data using a fast concurrent static HTTP fetcher (HTTP/3 + TLS fingerprinting).
  • Self-heals broken scrapers by recovering elements based on layout and similarity heuristics when selectors fail.

Quick start

from whispercrawler import Crawler, GhostCrawler, ShadowCrawler, Spider, Response

# Static HTTP fetch (fastest)
page = Crawler.get("https://example.com")
print(page.css("h1::text").get())

# JavaScript-heavy site
page = GhostCrawler.fetch("https://spa-example.com", headless=True)
items = page.css(".product-card")

# Cloudflare-protected site
page = ShadowCrawler.fetch("https://protected.example.com")
price = page.css(".price::text").get()

# Adaptive parsing — survives site redesigns
page = Crawler.get("https://example.com")
title = page.css("h1", auto_save=True)           # saves fingerprint
# Later, after site redesign — finds element by similarity
title = page.css("h1", adaptive=True)

# Spider
class QuoteSpider(Spider):
    name = "quotes"
    start_urls = ["https://quotes.toscrape.com/"]
    concurrent_requests = 10

    async def parse(self, response: Response):
        for quote in response.css(".quote"):
            yield {
                "text":   quote.css(".text::text").get(),
                "author": quote.css(".author::text").get(),
            }
        next_page = response.css("li.next a::attr(href)").get()
        if next_page:
            yield Request(url=response.url + next_page)

QuoteSpider().start()

Fetcher selection table

Fetcher When to use Backend Speed
Crawler Static HTML, APIs, JSON endpoints curl_cffi HTTP/3 Fastest
GhostCrawler JavaScript-rendered pages, SPAs Playwright/Patchright Chromium Medium
ShadowCrawler Cloudflare, advanced bot detection Camoufox (modified Firefox) Slower

Adaptive parsing

WhisperCrawler introduces self-healing element selection. By adding auto_save=True to your CSS or XPath calls, it saves a detailed structural fingerprint of the matched element to a local SQLite database. If a site undergoes a redesign and your selector stops matching, switching to adaptive=True allows WhisperCrawler to search the DOM for elements that closely match the stored fingerprint (using tag, text similarity, attribute overlap, and DOM depth calculation), returning the closest match automatically.

Installation

pip install whispercrawler
pip install "whispercrawler[fetchers]"   # for GhostCrawler and ShadowCrawler
pip install "whispercrawler[mcp]"        # for MCP server
whispercrawler install                   # download browser binaries

CLI reference

Command Options Description
whispercrawler install --force Download browser binaries required for Ghost/Shadow fetchers
whispercrawler get <url> --stealth, --ghost, --css <sel>, --xpath <sel>, --output <type>, --adaptive Fetch URL and extract elements via CLI
whispercrawler shell Launch interactive Python shell with preloaded environment

MCP server setup

WhisperCrawler includes a Model Context Protocol (MCP) server that exposes scraping tools to AI agents like Claude Desktop or OpenCode.

Configure your agent's MCP settings to add the whispercrawler server via stdio:

{
  "mcpServers": {
    "whispercrawler": {
      "command": "whispercrawler-mcp",
      "args": []
    }
  }
}

Session usage

Maintain shared persistent state (cookies, connection pools, proxies) across multiple requests using sessions.

from whispercrawler import CrawlerSession, GhostSession, ShadowSession

# Static requests
with CrawlerSession(browser_type="chrome") as session:
    page1 = session.get("https://example.com/login")
    page2 = session.post("https://example.com/api", json={"user": "foo"})

# Playwright SPA session
with GhostSession(headless=True, max_pages=3) as session:
    page = session.fetch("https://example.com")

# Camoufox stealth session
with ShadowSession(humanize=True) as session:
    page = session.fetch("https://protected.com")

ProxyWheel usage

Efficiently rotate through a pool of proxies using ProxyWheel. It automatically quarantines failed proxies for 5 minutes.

from whispercrawler import Crawler, ProxyWheel

rotator = ProxyWheel(["http://proxy1:8080", "http://proxy2:8080"], strategy="least_used")

# Apply to a single request
page = Crawler.get("https://example.com", proxy_rotator=rotator)

# Or apply globally to the class
Crawler.proxy_rotator = rotator

Interactive shell

The interactive shell provides a quick scratchpad to test scraping logic without writing full scripts. Running whispercrawler shell launches an IPython REPL with all fetcher classes, a persistent session history, and handy macros (like curl2crawler()) pre-imported to immediately begin querying pages interactively.

License

BSD 3-Clause License

Copyright (c) 2025, WhisperCrawler Contributors

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

whispercrawler-0.1.0.tar.gz (435.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

whispercrawler-0.1.0-py3-none-any.whl (190.0 kB view details)

Uploaded Python 3

File details

Details for the file whispercrawler-0.1.0.tar.gz.

File metadata

  • Download URL: whispercrawler-0.1.0.tar.gz
  • Upload date:
  • Size: 435.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for whispercrawler-0.1.0.tar.gz
Algorithm Hash digest
SHA256 956e36c273360ff68b3bb5d89f20b949ad60641c06df06b300fca9262b9b02e1
MD5 f0c8188004df90a4e5ab5f9c0ccf63a7
BLAKE2b-256 ed6b03b4f54623c8f7c3db9a1d90d85a401edb73d1320cb1861d65b4a1637bc4

See more details on using hashes here.

File details

Details for the file whispercrawler-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: whispercrawler-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 190.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for whispercrawler-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6e921aece33fa4affb1b59ec444d39e18f88885985efe5b26649a075d954b519
MD5 0fccee5c850b34c5e15f90e8abd69c9c
BLAKE2b-256 40867e6734441f1c1ecdbf8ff66f22cacb9f17cd95b6a2a2450647a202fb688d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page