OpenSource-Hub

crawl4ai

Library

unclecode/crawl4ai

Open-source LLM friendly web crawler for clean Markdown output.

Overview

Crawl4AI is an open-source web crawler designed to produce clean, structured Markdown for LLM consumption. It features asynchronous crawling, caching, anti-bot detection, and adaptive intelligence, deployable anywhere without API keys.

README Preview

# 🚀🤖 Crawl4AI: Open-source LLM Friendly Web Crawler & Scraper.\n\n\n\n\n\n[](https://github.com/unclecode/crawl4ai/stargazers)\n[](https://github.com/unclecode/crawl4ai/network/members)\n\n[](https://badge.fury.io/py/crawl4ai)\n[](https://pypi.org/project/crawl4ai/)\n[](https://pepy.tech/project/crawl4ai)\n[](https://github.com/sponsors/unclecode)\n\n---\n#### 🚀 Crawl4AI Cloud API — Closed Beta (Launching Soon)\nReliable, large-scale web extraction, now built to be _**drastically more cost-effective**_ than any of the existing solutions.\n\n👉 **Apply [here](https://forms.gle/E9MyPaNXACnAMaqG7) for early access**  \n_We’ll be onboarding in phases and working closely with early users.\nLimited slots._\n\n---\n\n\n    \n      \n    \n    \n      \n    \n    \n      \n    \n  \n\n\nCrawl4AI turns the web into clean, LLM ready Markdown for RAG, agents, and data pipelines. Fast, controllable, battle tested by a 50k+ star community.\n\n[✨ Check out latest update v0.8.6](#-recent-updates)\n\n✨ **New in v0.8.6**: Security hotfix — replaced `litellm` with `unclecode-litellm` due to a PyPI supply chain compromise. If you're on v0.8.5, please upgrade immediately.\n\n✨ Recent v0.8.5: Anti-Bot Detection, Shadow DOM & 60+ Bug Fixes! Automatic 3-tier anti-bot detection with proxy escalation, Shadow DOM flattening, deep crawl cancellation, config defaults API, consent popup removal, and critical security patches. [Release notes →](https://github.com/unclecode/crawl4ai/blob/main/docs/blog/release-v0.8.5.md)\n\n✨ Previous v0.8.0: Crash Recovery & Prefetch Mode! Deep crawl crash recovery with `resume_state` and `on_state_change` callbacks for long-running crawls. New `prefetch=True` mode for 5-10x faster URL discovery. [Release notes →](https://github.com/unclecode/crawl4ai/blob/main/docs/blog/release-v0.8.0.md)\n\n✨ Previous v0.7.8: Stability & Bug Fix Release! 11 bug fixes addressing Docker API issues, LLM extraction improvements, URL handling fixes, and dependency updates. [Rele

FAQ (5)

Troubleshooting
Why do API hooks fail with 'ImportError: __import__ not found' in crawl4ai v8.0.0 Docker?

This is a known regression in v8.0.0 caused by an over‑restrictive builtins whitelist (PR #1712). The hook manager's internal compilation step runs exec("import asyncio", namespace) which requires the __import__ built‑in, but it was removed from the allowed list. Any user‑provided hook, even a trivial one, triggers this error.

**Workarounds:**
- **Downgrade** to v7.x (e.g., unclecode/crawl4ai:v7.0.0)
- **If you control the container**, edit hook_manager.py and either:
1. Add '__import__' back to the allowed_builtins list, or
2. Replace the exec("import asyncio") / exec("import json") lines with direct assignments:

import asyncio, json
     namespace['asyncio'] = asyncio
     namespace['json'] = json

Track issue #1878 for the permanent fix.

GitHub Issue #1878
Troubleshooting
Why are sentences returned in random order when using NlpSentenceChunking in crawl4ai?

This is a known bug in crawl4ai where NlpSentenceChunking.chunk() uses list(set(sens)), which shuffles sentences because Python set is unordered. The fix has been merged into the develop branch and will be included in the next release.

**Workaround**: Apply the fix manually by editing chunking_strategy.py and changing:

return list(set(sens))  # BUG

to:
return sens

Or install directly from the fix branch:

pip install git+https://github.com/unclecode/crawl4ai.git@develop

The fix preserves document order and keeps intentional duplicate sentences.

GitHub Issue #1909
Troubleshooting
How to fix 'Deserialization of type LLMTableExtraction is not allowed' error in crawl4ai Docker Job Queue API?

This bug was caused by LLMTableExtraction missing from the deserialization allowlist in async_configs.py. It is fixed in crawl4ai v0.8.7 and later. To resolve, upgrade to the latest version:

docker pull ghcr.io/unclecode/crawl4ai:latest

If using pip, update with pip install crawl4ai>=0.8.7. Restart your Docker container to apply the fix.

GitHub Issue #1924
Troubleshooting
Why does crawl4ai ignore semaphore_count and cause 429 'Too Many Requests' errors?

It's a known bug where DeepCrawlStrategy creates a MemoryAdaptiveDispatcher that ignores the semaphore_count setting from your CrawlerRunConfig, defaulting to 20 concurrent tasks and triggering rate limits. The fix reads semaphore_count from the config and passes it as max_session_permit.

**Solution: Upgrade to version 0.8.7 or later:**

pip install --upgrade crawl4ai

**If you need a temporary workaround**, apply this change to your local installation (pre‑0.8.7):

Edit crawl4ai/async_webcrawler.py near line 1032:

max_session_permit = max(1, int(getattr(primary_cfg, "semaphore_count", 5) or 5))
dispatcher = MemoryAdaptiveDispatcher(
    max_session_permit=max_session_permit,
    ...
)

Or install the patched branch:

pip install git+https://github.com/hafezparast/crawl4ai.git@fix/maysam-dispatcher-semaphore-count-1927

After the fix, semaphore_count in your config will properly control concurrency and prevent 429 errors.

GitHub Issue #1927
Troubleshooting
Why doesn't enable_stealth=True hide navigator.webdriver in crawl4ai 0.8.6?

In crawl4ai 0.8.6, the StealthAdapter incorrectly imports stealth_async/stealth_sync from playwright-stealth 2.x, causing stealth to be silently skipped. Upgrade to crawl4ai 0.8.7, which updates the adapter to use the Stealth class:

pip install --upgrade crawl4ai==0.8.7

If you cannot upgrade immediately, a temporary workaround is to downgrade playwright-stealth to the 1.x series:

pip install 'playwright-stealth<2'

(Note that this may conflict with other dependencies.)

GitHub Issue #1959