Skip to main content

crawlr

crawlr

An AI-powered, self-healing web scraper for e-commerce price & stock monitoring.

PyPI version Python versions License: MIT Website

Website · PyPI · pip install crawlr


Crawlr uses an LLM (or a free offline heuristic) only to generate and repair CSS selectors, then extracts pages deterministically with those cached selectors. When a site changes its layout and the selectors break, Crawlr detects it and regenerates them automatically — so your monitoring never silently dies.

  • Runs free & offline — no API key required; add an OpenAI/Anthropic key for higher accuracy.
  • Self-healing — survives redesigns that break traditional scrapers.
  • Zero-config — crawlr watch <url> auto-detects the right schema (product, jobs, real estate, news).
  • Price & stock alerts — webhook (signed), Slack, Discord, Teams, Telegram, ntfy, or email, with throttling.
  • General-purpose — e-commerce ships in; add new verticals as simple YAML.

Install

pipx install crawlr        # or: pip install crawlr

Quickstart

crawlr watch "https://store.com/product/123" --target 25   # schema auto-detected
crawlr watchlist                                           # current price, movement, stock
crawlr monitor --daemon                                    # keep checking in the background
crawlr serve                                               # optional local dashboard

Omit --schema and Crawlr detects the page type for you (product, product list, jobs, real estate, news). Pass --schema <name> to override.

Deploy with Docker

docker run -p 8000:8000 -v crawlr-data:/data ghcr.io/ardfaiyaz/crawlr   # dashboard on :8000

Or run the dashboard and a background monitor together:

docker compose up -d      # then open http://localhost:8000

Build locally with docker build -t crawlr .. Data (SQLite DB, selector cache, snapshots) persists in the /data volume.

Alert triggers

Pick one per watch with --trigger (or in the dashboard):

Trigger Alerts when
any_change any watched field changes
price_drop the price goes down
price_below price is at/below your target
price_above price is at/above your target
back_in_stock the item becomes available
out_of_stock the item sells out

For richer logic, run crawlr init to create an editable crawlr.rules.yaml that maps circumstances to actions (and overrides per-watch triggers):

default_action: ignore
rules:
  - when: price_drops_below
    amount: 25
    action: alert
  - when: back_in_stock
    action: alert

Every option, explained

crawlr watch <url> [options] — start tracking a product page or a store's product list.

Option What it does
--target 500 Ping me when the price drops to 500 or below (also sets the trigger to price_below)
--restock Ping me when the item goes from out of stock → in stock
--trigger <name> Choose exactly when to be alerted (see the table below)
--interval 60 Check this page every 60 minutes (default: 60)
--schema <name> Force the page type instead of auto-detecting: product, product_list, jobs, real_estate, news

Triggers (--trigger ...), in plain English:

Trigger Alerts you when…
any_change anything you watch changes (price, stock, title…)
price_drop the price goes down by any amount
price_below the price is at or below your --target
price_above the price is at or above your --target
back_in_stock the item becomes available again
out_of_stock the item sells out

The commands you'll actually use:

Command What it does
crawlr watch <url> Start tracking a product or store page
crawlr watchlist Show everything you track: price, change, stock, status
crawlr monitor Check all due pages once, right now
crawlr monitor --daemon Keep checking forever in the background
crawlr compare <url> <url> … One-off price comparison across several links
crawlr insights <id> Price analytics: all-time low/high, average, "deal score"
crawlr pause <id> / resume <id> Temporarily stop / restart tracking one item
crawlr unwatch <id> Stop tracking an item and delete its history
crawlr serve Open the web dashboard at http://localhost:8000
crawlr doctor Check that your setup works
crawlr test-alert Send a test notification so you know alerts reach you

The <id> numbers come from crawlr watchlist or crawlr sites.

Recipes

# Track a competitor's price, alert on a 10%+ drop, check hourly
crawlr watch "https://store.com/p/123" --trigger price_drop --interval 60

# Get pinged when something is back in stock
crawlr watch "https://store.com/p/123" --restock

# Compare the same product across three shops
crawlr compare "https://a.com/p" "https://b.com/p" "https://c.com/p"

# Monitor a job board (schema auto-detected)
crawlr watch "https://boards.example/jobs" --interval 720

# Free phone alerts via ntfy.sh
export CRAWLR_ALERT_NTFY="https://ntfy.sh/my-crawlr-alerts"
crawlr monitor --daemon

# Pause / resume / remove a watch
crawlr pause 3 && crawlr resume 3 && crawlr unwatch 3

# Pipe machine-readable output into other tools
crawlr watchlist --json | jq '.[] | {title, price}'

Custom schemas (no code)

Add new verticals by dropping a YAML file into your schema directory:

name: jobs
item_selector: ".job-card"
fields:
  - name: title
    description: the job title
    type: text
    required: true
  - name: salary
    description: annual salary
    type: number

Then crawlr scrape <url> --schema jobs. List schemas with crawlr schemas.

Configuration

Set via environment variables or a .env file:

Variable Default Description
CRAWLR_LLM_PROVIDER none openai, anthropic, or none (offline heuristic)
CRAWLR_LLM_API_KEY — API key for the chosen provider
CRAWLR_DATABASE_URL — postgresql://... to use Postgres instead of SQLite
CRAWLR_ALERT_WEBHOOK — Webhook URL for change alerts
CRAWLR_ALERT_SLACK — Slack incoming-webhook URL
CRAWLR_ALERT_DISCORD — Discord incoming-webhook URL
CRAWLR_ALERT_TEAMS — Microsoft Teams incoming-webhook URL
CRAWLR_ALERT_NTFY — ntfy.sh (or self-hosted) topic URL
CRAWLR_ALERT_TELEGRAM_TOKEN — Telegram bot token (from @BotFather)
CRAWLR_ALERT_TELEGRAM_CHAT_ID — Telegram chat id to send alerts to
CRAWLR_WEBHOOK_SECRET — HMAC-signs generic webhook payloads
CRAWLR_ALERT_THROTTLE_MINUTES 0 Suppress repeat alerts within N minutes
CRAWLR_PROXIES — Comma-separated proxy URLs to rotate
CRAWLR_RESPECT_ROBOTS true Honor robots.txt
CRAWLR_FX_BASE USD Currency that compare converts prices into
CRAWLR_FX_LIVE false Fetch live FX rates (cached) instead of the pinned table
CRAWLR_FX_API_URL open.er-api.com Live FX endpoint ({"rates": {CODE: perUSD}})
CRAWLR_FX_RATES — Pinned rate overrides, e.g. EUR=0.92,GBP=0.79

Examples

Ready-to-run recipes live in examples/ — watch competitors, use a custom schema, and call the hosted API from Python.

Development

pip install -e '.[dev]'
pytest          # offline test suite
ruff check .    # lint
crawlr eval     # extraction accuracy gate

Contributing

Contributions are welcome — see CONTRIBUTING.md. Great first contributions: new vertical presets, golden eval cases for sites that extract wrong, and docs/examples.

Demo

A short GIF is the best intro. Generate one with VHS: vhs docs/demo.tape → docs/demo.gif (see docs/DEMO.md).

Does it work on big marketplaces (Lazada, Shopee, Amazon)?

Short answer: it can, but they're the hardest sites to scrape — expect extra setup, and don't count on 100% reliability.

Crawlr shines on sites with clean HTML or embedded product data (schema.org JSON-LD). Big marketplaces are deliberately hostile to bots, in three ways — here's how to give Crawlr its best shot:

  1. They render prices with JavaScript. The price often isn't in the raw HTML; it loads after the page runs its scripts. Install the browser engine so Crawlr can render it:

    pip install "crawlr[js]"
    playwright install chromium
    

    Then pass --js (e.g. crawlr watch "<url>" --js) or let Crawlr auto-escalate when it detects a JS-only shell.

  2. They have anti-bot protection (Cloudflare, CAPTCHAs, rate limits). Crawlr detects when it's blocked and skips that run instead of saving a bogus price — but getting through reliably usually needs rotating proxies:

    export CRAWLR_PROXIES="http://user:pass@host:port,http://host2:port"
    
  3. robots.txt — many marketplaces disallow scraping these pages, and Crawlr honors robots.txt by default, so it may refuse to fetch. Only override this for sites you're permitted to scrape (see Legal & responsible use below):

    export CRAWLR_RESPECT_ROBOTS=false
    

Rule of thumb:

Site type How well it works
Independent shops, Shopify / WooCommerce, anything with schema.org data ✅ Works well out of the box
A marketplace's official API (if it offers one) ✅ Most reliable — prefer this
Lazada / Shopee / Amazon product pages ⚠️ Possible with crawlr[js] + proxies; may still get blocked
Pages behind a login, or a CAPTCHA on every request ❌ Not a good fit

Tip: prove the whole flow works on an easy site first, then point it at the hard one:

crawlr watch "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html" --target 60
crawlr watchlist

Crawlr is a general-purpose scraping tool, and you are responsible for how you use it. Before monitoring any site, make sure you comply with:

  • the target site's Terms of Service and robots.txt — Crawlr honors robots.txt by default, so keep CRAWLR_RESPECT_ROBOTS=true unless you own the site;
  • applicable laws such as the CFAA (US) and GDPR/CCPA whenever personal data is involved — prefer public, non-personal data and avoid collecting PII;
  • reasonable rate limits — use sensible intervals and delays so you don't overload a site.

Crawlr is meant for legitimate uses such as tracking your own listings, price research, and public-data monitoring. Please don't use it to bypass authentication, paywalls, or anti-abuse protections. The maintainers provide the software "as is" and are not responsible for how it is used (see LICENSE).

License

Crawlr is released under the MIT License — free to use, modify, and distribute, including commercially. See LICENSE.

Building a commercial or hosted product on top of Crawlr? An open-core model works well: keep the CLI and library MIT-licensed (this repo) and offer any hosted service, team features, or premium connectors as a separate paid layer.

Metadata

Release files for crawlr 0.3.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 crawlr 0.3.0
File Size Uploaded
crawlr-0.3.0.tar.gz 71.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for crawlr 0.3.0
File Interpreter ABI Platform
crawlr-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 158.5 kB

Release files / crawlr-0.3.0.tar.gz

Download URL crawlr-0.3.0.tar.gz
Size 71.3 kB
Tags Source
SHA-256 checksum
How to use checksums
741218eb8a15930e388420acb191e4c90ce7cdce80f6c7479baefc016f6145c0
BLAKE2b-256 checksum
How to use checksums
325e2e54846cb111a9a2061b185647b35410da05c55b1259a22d28e2d2fc0696
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 20, 2026.

Transparency log

Release files / crawlr-0.3.0-py3-none-any.whl

Download URL crawlr-0.3.0-py3-none-any.whl
Size 87.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d68c64a09856cbd8761fe495595dbd8d940d7f2b2f3aca869a09788adaff381b
BLAKE2b-256 checksum
How to use checksums
d1ed7811781ba390523842e6e237133fdfc3a2573dc1bf49bddf99c6a632789a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 20, 2026.

Transparency log

Release history Release notifications | RSS feed

0.10.0

2 release files

0.8.0

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

This release

0.3.0 This release

2 release files

0.2.0

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