Skip to main content
Onecrawler

Onecrawler

Crawling hard? Not anymore.

Async Python crawling library with sitemap discovery, browser-based extraction, and LLM-powered structured output — one Settings object drives it all.

CI Python PyPI Code style: black Imports: isort License: MIT

Installation · Quick Start · CLI · Documentation


Overview

Onecrawler helps you build maintainable crawling and extraction workflows without turning every project into a custom scraping script. It provides a shared configuration model, async execution, sitemap discovery, browser-backed link extraction, heuristic content extraction, and optional GenAI extraction for typed outputs.

Recommended workflow:

  1. Use sitemaps first whenever possible.
  2. Fall back to browser link extraction when sitemap coverage is missing or dynamic.
  3. Scrape the final URL list with heuristic extraction by default.
  4. Use GenAI extraction when you need structured output in a Pydantic schema.
async with LinkExtractor(settings) as link_engine:
    links = await link_engine.run("https://example.com")

async with Scraper(settings) as scraper_engine:
    records = await scraper_engine.run(links)  # [{"url": ..., "result": ...}, ...]

Features

Capability Details
Sitemap discovery Resolves robots.txt, common sitemap paths, nested indexes, .xml.gz, feeds, and HTML fallback
Browser link extraction Shallow and deep Playwright-backed discovery for JavaScript-rendered or sitemap-poor sites
URL filtering Wildcard path filters with include_link_patterns
Content filtering Composable post-extraction filters by date, keywords, file type, and cosine similarity with AND/OR/NOT logic
Async performance Tunable concurrency, retries, timeouts, and crawl limits
Content extraction Heuristic extraction with trafilatura for fast article-like content
Markdown conversion Whole-page HTML-to-Markdown fallback for pages heuristic extraction can't handle (non-article, e-commerce, dashboards)
GenAI extraction Optional model-assisted extraction for strongly typed Pydantic outputs
Output formats markdown, json, xml, xmltei
Proxy support Single proxy or rotating proxy pools for browser and sitemap workflows
Browser controls Viewport, user agent, locale, timezone, storage state, and runtime settings

When To Use What

Need Use Why
Fast URL discovery from a public site SiteMap Simplest, fastest, and least expensive way to collect URLs
Links from one listing page Shallow LinkExtractor Reads direct same-site links from the page
Recursive discovery through navigation Deep LinkExtractor Follows internal links until your configured limit
Bulk article or page text extraction Heuristic Scraper Deterministic and avoids model cost
Non-article pages (product, docs, dashboards) markdownify Scraper Never returns empty; heuristic extraction is article-biased
Typed fields or semantic normalization GenAI extraction Produces schema-shaped output for downstream systems

Installation

pip install onecrawler

Install Playwright browser binaries when you use browser-backed crawling or scraping:

python -m playwright install chromium

For local development:

git clone https://github.com/sayedshaun/onecrawler.git
cd onecrawler
python -m pip install -e ".[dev]"
python -m playwright install chromium

Docker Support

OneCrawler provides an optimized Docker image that includes all necessary browser dependencies. This is the recommended way to run onecrawler in production or CI/CD environments.

Build the Image

docker pull ghcr.io/sayedshaun/onecrawler:latest

You can rename it for convenience

docker tag ghcr.io/sayedshaun/onecrawler:latest onecrawler

Run a Script with Docker

docker run -it --rm -v $(pwd):/app onecrawler python your_script.py

Run the Built-in CLI with Docker

docker run --rm onecrawler python -m onecrawler crawl https://example.com --limit 20

Command-Line Interface

For a quick one-off crawl without writing a script:

python -m onecrawler crawl https://example.com --limit 20 --concurrency 5

Each extracted page is printed to stdout as a JSON line. Run python -m onecrawler crawl --help for the full flag list (--strategy, --format, --include, --exclude). The CLI covers heuristic-strategy crawling only — proxies, GenAI extraction, and human-behavior simulation need the Python API below.


Quick Start

from onecrawler import Settings, Crawler
from onecrawler.utils import writter

async def main():
    settings = Settings(link_extraction_limit=100, concurrency=5)

    async with Crawler(settings) as engine:
        results = await engine.run("https://www.prothomalo.com/")

    writter.dump_json(results, "output.json")


if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

Separate Workflow

from onecrawler import HumanBehaviorSettings, LinkExtractor, Scraper, Settings
from onecrawler.utils import writter

async def main():
    settings = Settings(
        link_extraction_strategy="deep",
        link_extraction_limit=10,
        concurrency=7,
        scraping_strategy="heuristic",
        scraping_output_format="json",
        human_behavior_settings=HumanBehaviorSettings(),
    )

    async with LinkExtractor(settings) as link_engine:
        links = await link_engine.run("https://www.example.com/")

    async with Scraper(settings) as scraper_engine:
        results = await scraper_engine.run(links)  # [{"url": ..., "result": ...}, ...]

    writter.dump_json(results, "output.json")


if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

Use browser extraction when sitemaps are incomplete, unavailable, or unable to expose JavaScript-rendered links.

import asyncio
from onecrawler import Settings, LinkExtractor


async def main():
    settings = Settings(
        link_extraction_strategy="deep",
        link_extraction_limit=250,
        include_link_patterns=["/news/*"],
        concurrency=5,
    )

    async with LinkExtractor(settings) as engine:
        links = await engine.run("https://example.com/news")

    print(f"Collected {len(links)} links")


if __name__ == "__main__":
    asyncio.run(main())

Content Filtering

Filter crawled results by date, keywords, file type, or semantic similarity. Filters are passed to Crawler.run() or Crawler.stream() and applied after content extraction.

import asyncio
from onecrawler import Crawler, Settings
from onecrawler.filters import AND, by_date, by_keywords


async def main():
    settings = Settings(
        link_extraction_limit=50,
        concurrency=5,
    )

    # Keep only pages from 2025 that mention "python" or "async"
    content_filter = AND(
        by_date(start="2025-01-01", end="2025-12-31"),
        by_keywords(["python", "async"]),
    )

    async with Crawler(settings) as engine:
        results = await engine.run(
            "https://example.com/blog",
            filters=content_filter,
        )

    print(f"Matched {len(results)} pages")


if __name__ == "__main__":
    asyncio.run(main())

Available Filters

Filter Import Purpose
by_date(start, end) onecrawler.filters Keep items within a YYYY-MM-DD date range
by_keywords(keywords) onecrawler.filters Keep items whose text contains any keyword
by_files(types) onecrawler.filters Keep items by logical file type (pdf, image, docx, text)
by_extension(extensions) onecrawler.filters Keep items by URL file extension (.pdf, .jpg)
by_cosine_similarity(query, threshold) onecrawler.filters Keep items whose text is semantically similar to a query

Composing Filters

Use AND, OR, and NOT from onecrawler.filters to combine filters:

from onecrawler.filters import AND, OR, NOT, by_date, by_keywords, by_files

# Pages from 2025 that mention "python" but are not PDFs
f = AND(
    by_date(start="2025-01-01"),
    by_keywords(["python"]),
    NOT(by_files(["pdf"])),
)

# Pages that mention "AI" or are from 2025
f = OR(
    by_keywords(["AI"]),
    by_date(start="2025-01-01", end="2025-12-31"),
)

Streaming With Filters

Filters work with Crawler.stream() for real-time filtered output:

async with Crawler(settings) as engine:
    async for item in engine.stream(
        "https://example.com/news",
        filters=by_cosine_similarity("climate policy", threshold=0.3),
    ):
        print(item["title"])

GenAI Extraction With a Schema

Use GenAI extraction when you need a strongly typed response shape instead of plain content.

import asyncio
from typing import Optional
from pydantic import BaseModel
from onecrawler import Settings, LLMSettings, Scraper


class ArticleSummary(BaseModel):
    title: str
    author: Optional[str] = None
    published_at: Optional[str] = None
    summary: str
    topics: list[str]


async def main():
    settings = Settings(
        scraping_strategy="genai",
        scraping_output_format="json",
        genai=LLMSettings(
            provider="openai",
            model_name="gpt-4o-mini",
            api_key="YOUR_API_KEY",
            output_schema=ArticleSummary,
        ),
        concurrency=2,
        request_timeout=30,
    )

    async with Scraper(settings) as scraper:
        item = await scraper.run("https://example.com/articles/story")

    result = item["result"]
    print(result.model_dump() if hasattr(result, "model_dump") else result)


if __name__ == "__main__":
    asyncio.run(main())

Supported Providers

Provider Requires Models
OpenAI api_key (optional with a custom base_url) GPT-4o, GPT-4o-mini, or any OpenAI-compatible server
Google api_key Gemini models
Ollama base_url (no key needed) Any locally hosted model

Ollama Example

settings = Settings(
    scraping_strategy="genai",
    genai=LLMSettings(
        provider="ollama",
        model_name="llama3:8b",
        base_url="http://localhost:11434/",
        output_schema=ArticleSummary,
    ),
)

Proxy Support

Attach one proxy or a rotating proxy pool directly to Settings.

from onecrawler import Settings, ProxySettings


settings = Settings(
    proxies=[
        ProxySettings(server="http://proxy-1.example:8080"),
        ProxySettings(
            server="http://proxy-2.example:8080",
            username="user",
            password="pass",
        ),
    ],
    proxy_rotation_method="round_robin",
)

Use proxies=[ProxySettings(...)] for a single proxy (a one-element list), or add more entries with proxy_rotation_method for a pool.


Production Tips


License

Released under the MIT License. See LICENSE for full terms.

Metadata

Release files for onecrawler 0.1.9

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

Source distribution (sdist)

Source distribution for onecrawler 0.1.9
File Size Uploaded
onecrawler-0.1.9.tar.gz 72.3 kB Details

Built distribution (wheel)

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

Total release size: 143.2 kB

Release files / onecrawler-0.1.9.tar.gz

Download URL onecrawler-0.1.9.tar.gz
Size 72.3 kB
Tags Source
SHA-256 checksum
How to use checksums
7199b24b1c2fcdf98b25f1a15ed4abd9b0e7a21e840d99ee2d42c96dedfd57f0
BLAKE2b-256 checksum
How to use checksums
c555984c1ad6f952ac00dde1a47273222310a1a54237eba861ae84f83065ef1a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / onecrawler-0.1.9-py3-none-any.whl

Download URL onecrawler-0.1.9-py3-none-any.whl
Size 70.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c853e38c16f02d1f9091c2dca6b02236375c26ba079ba94528c64caa023b1d3f
BLAKE2b-256 checksum
How to use checksums
f65b64225f1c6e1b15c30ab89fad4c00036e26f52bf6439c4c08398aed78514a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.1.9 This release

2 release files

0.1.8

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