unclecode / unclecode/crawl4ai

[Bug]: BFSDeepCrawlStrategy re-scans the full level for parent lookup (O(n²)); BestFirstCrawlingStrategy can enqueue the same URL twice

Open
#2,242 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

⚙ Done 🐞 Bug
Dominant language
Python
Stars
83.9k
Forks
8.7k
Avg merge
3d 7h
Merged PRs (30d)
11

Description

crawl4ai version

0.9.3

Expected Behavior
  • Per-level bookkeeping in BFSDeepCrawlStrategy (matching a fetched result back to its parent URL) should scale linearly with the number of URLs in a level.
  • A URL discovered by multiple pages in BestFirstCrawlingStrategy should be scored and queued once, not once per inbound link.
Current Behavior
  1. O(n²) parent lookup - deep_crawling/bfs_strategy.py, _arun_batch and _arun_stream:

parent_url = next((parent for (u, parent) in current_level if u == url), None)

This linearly re-scans the entire current_level list once per fetched result. For a level of N URLs this is O(N²) pure-Python work with no I/O involved - a page with high fan-out (hundreds/thousands of links) makes this bookkeeping step dominate.

  1. Duplicate enqueue - deep_crawling/bff_strategy.py, link_discovery/ _arun_best_first:
    visited is only populated when an item is dequeued, not when it's discovered, so link_discovery's dedup check (if base_url in visited: continue) doesn't stop the same URL being pushed onto the priority queue twice if two different pages link to it before it's first processed. The duplicate is silently dropped later at dequeue time, so output is still correct, but it was scored and queued for nothing.
Is this reproducible?

Yes

Inputs Causing the Bug
- URL(s): Any site with high link fan-out per page, or shared links between sibling pages
- Settings used: BFSDeepCrawlStrategy(max_depth=2, max_pages=1000+) for issue 1; BestFirstCrawlingStrategy(...) with a url_scorer for issue 2
Steps to Reproduce
1. Run `BFSDeepCrawlStrategy` against a page with hundreds+ of internal links at depth 1; profile `_arun_batch`'s per-result loop - the parent lookup dominates as level size grows.
2. Run `BestFirstCrawlingStrategy` against a small site where ≥2 pages link to the same third page before it's first crawled; log `queue.qsize()` or inspect enqueued items - the shared URL appears twice.
Code snippets

OS

macOS 26.6.2 (Darwin 25.6.0)

Python version

3.13.12

Browser

No response

Browser version

No response

Error logs & Screenshots (if applicable)

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading deep_crawling/bfs_strategy.py in _arun_batch and _arun_stream, then deep_crawling/bff_strategy.py in link_discovery and _arun_best_first. Reproduce the high-fan-out BFS case and the shared-link BestFirst case described in the issue. Done means parent matching scales linearly and each discovered URL is scored and queued only once.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.