pagesift

YOLOW92AGPL-3.0活跃维护

自托管的网页抓取与文档解析服务,把 URL、带 OCR 的 PDF 和 Office 文件转成干净的 Markdown/JSON 供 AI Agent 使用,兼容 Firecrawl 和 Jina 接口,单个 Rust 二进制即可部署。

Self-hosted web scraper, crawler and document parser for AI agents: URLs, PDFs with OCR and Office files to clean Markdown/JSON. Firecrawl- and Jina-compatible API, MCP server, agent endpoint, Python/Node SDKs. Single Rust binary.

v1.2.4发布于 2026-11-09 10:10 UTC262star +10 / 7 天33fork同步于 2026-11-10 18:03 UTC

怎么上手

由 README 提炼,执行前请确认
cargo install pagesift --locked
pagesift scrape https://example.com
硬件要求按 README 说明

HTTP、PDF、Office 解析无需额外安装;JavaScript 页面需可选浏览器,OCR 可用 NVIDIA GPU,带公式模型的 OCR 约需 1.7 GB 内存;无浏览器时单 worker 峰值 18–377 MB。支持 Linux x86_64/aarch64、macOS arm64、Windows x86_64。

有 Docker 镜像
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

自托管 Rust 单二进制,把网页、PDF、Office 转成干净 Markdown/JSON 喂给 AI Agent

自托管的网页抓取与文档解析服务,把 URL、带 OCR 的 PDF 和 Office 文件转成干净的 Markdown/JSON 供 AI Agent 使用,兼容 Firecrawl 和 Jina 接口,单个 Rust 二进制即可部署。

核心能力

  • 用自研 Rust 解析器读取 PDF、Office、电子书、邮件和压缩包
  • 用 PP-OCRv6 在 CPU 或 NVIDIA GPU 上识别扫描件与公式
  • 兼容 Firecrawl v1/v2 与 Jina Reader 的 HTTP 接口
  • 提供 MCP 服务与 Python/Node 等多语言 SDK
  • 按 CSS 选择器或模型生成的 schema 抽取结构化 JSON

容易踩的坑

OCR 模型在首次使用时才下载,需提前联网或预置;JavaScript 页面要另装浏览器,可用 pagesift doctor 检查;Docker 服务默认监听 3002 端口,且需设置 PAGESIFT_API_KEYS 才能带鉴权调用。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v1.2.4
  1. v1.2.4最新正式版2026-11-09 · 2026-11-09 10:10 UTC

    PageSift 1.2.4 Release Notes

    Release Version: v1.2.4 License: AGPL-3.0-only (Commercial licensing available)

    Changes since 1.2.3.

    Attachment authorization

    • Problem: GET /v2/attachments/{id} checked only the API key and not resource ownership. A valid key for one account could download an attachment produced for another account when the ID was known. IDs are content-derived SHA-256 prefixes and also appear in rewrite Markdown (asset://<id>), JSON results and logs, so they are not a secret.
    • Fix: the download endpoint now requires an (account, attachment) authorization record before reading bytes. A missing or expired record returns the same 404 response as a missing attachment, with the message attachment {id} not found or expired, so the response does not reveal whether the attachment exists. Content addressing and cross-account deduplication are unchanged: every account that receives an attachment in a scrape, batch, crawl or parse result gets its own authorization record.
    • Migration: on startup, missing authorizations are backfilled from saved job results, using the job owner and the attachment IDs in each page. Backfill runs in the background; failures are logged as warnings and do not block startup. Attachments referenced by persisted batch and crawl results keep working for their owning account for the remainder of the 24-hour retention period. Attachments that were only produced by a synchronous scrape are not part of a saved job result and cannot be attributed to an account, so such a link is not backfilled after an upgrade.
    • Scope: multi-key deployments are affected. For new results, single-key and no-authentication deployments behave as before: when no API keys are configured, the anonymous identity is used for both writing and checking authorization. MCP attachments remain memory-only and are unaffected.
  2. v1.2.32026-11-09 · 2026-11-09 08:04 UTC
    查看更新说明

    PageSift 1.2.3 Release Notes

    Version: v1.2.3 · Date: 2026-11-09 · License: AGPL-3.0-only; commercial licensing available

    Changes since 1.2.2. Also available in 简体中文, 日本語, and Español.

    Image assets

    • imageAssets is opt-in on scrape and batch requests, or inside scrapeOptions for crawl. Omit it to retain the previous link-only output. attach keeps Markdown links and returns Base64 attachment bytes; embed writes data URLs into Markdown; rewrite uses asset://<id> references and returns attachments. The CLI supports --image-assets attach|embed|rewrite on scrape and crawl.
    • Assets report an ID derived from the SHA-256 of exported bytes, the complete hash, detected MIME type, byte count and source. The separate imageAssets outcomes include ok, skipped-limit and failed, with a reason when relevant. Image recognition uses content, not just filename extensions or HTTP Content-Type.
    • attach and rewrite publish identical bytes once per batch/crawl task. Later pages keep the same asset ID without another Base64 payload. With persistent jobs the asset bytes are stored in the content-addressed attachment store; the first page's inline payload is reconstructed when that page is read. Pagination clients should retain assets from earlier pages or use the attachment endpoint while available. embed instead keeps each page self-contained, so data URLs may repeat across pages.
    • Web images use the existing robots, rate-limit, redirect and SSRF policy. Each page has a byte budget, up to 64 image requests, a 10-second image deadline and at most four concurrent image fetches. Fetch failures and limit skips retain the original links. A bounded task-local cache shares up to 32 URLs with images up to 512 KiB; persistent job recovery repopulates it from saved successful sources. Larger images, additional URLs or different URLs with identical bytes can still require repeated downloads.
    • SVG is allowed as an attachment or asset:// reference, not as a new embed data URL. Identifying SVG does not sanitize it. Source-page data URLs are governed separately by removeBase64Images.
    • PDF XObject images use the asset pipeline independently of OCR. IDs hash the actual exported bytes, including images converted to PNG/TIFF, and PDF Markdown references follow the exported ID. PDF inline images are not included. DOCX, PPTX and XLSX ZIP media preserve their original bytes; email image attachments are not included in this pipeline.
    • HTTP scrape, batch and crawl return the asset data. With --out, CLI output writes images/<id> and includes outcomes in index.jsonl. MCP scrape returns image assets as native image content. In MCP embed mode, Markdown with data URLs is kept in the text block but omitted from structured content to avoid a further copy; native image blocks still duplicate the bytes present in the text.

    Streaming and compatibility

    • POST /v2/scrape/stream can send provisional extracted Markdown before image downloads complete, followed by the final scrape result. With ?previews=true, batch/crawl streams also emit provisional Markdown before their final page events. Previews are limited to 1 MiB, may be dropped, and are not replayed; final page sequence IDs and resume behavior are unchanged. Normal JSON results still wait for asset processing.
    • removeBase64Images: false is now accepted and preserves source-page data URL images in Markdown; the default true continues to remove them. Cache keys distinguish the two options.
    • Existing exportImages remains available. New-mode attachment JSON contains MIME, Base64 data for the first published copy and an inlineData marker. HTTP, CLI, MCP and stream details are in the [image asset guide](https://g
  3. v1.2.22026-11-08 · 2026-11-08 07:29 UTC
    查看更新说明

    PageSift 1.2.2 Release Notes

    Release Version: v1.2.2 License: AGPL-3.0-only (Commercial licensing available)

    Changes since 1.2.1.

    Security and fixes

    • Crawl and batch job listing, status, errors, streams and cancellation are scoped to the account that created the job. Extract job results are likewise restricted to their owner.
    • Search with page scraping and extract use the daily page quota. Each page attempt consumes a unit before it is fetched; when the quota is exhausted, further pages are not fetched.
    • A cached page is checked against robots.txt when the current request respects robots, including recorded redirect URLs.
    • Expired extract and agent jobs can no longer be retrieved or cancelled.
    • MCP placeholder outputs match their published output schemas. Nullable fields in the document schema match the serialized result.
    • Finishing an unreserved itna attempt no longer panics. The session-pool test fixture carries the Retry-After flag into outcome classification.

    Compatibility

    • storeSnapshot: true and removeBase64Images: false now return an unsupported-option error instead of being silently ignored. Change tracking is available through the changeTracking format.
    • With multiple API keys, an account can no longer access another account's crawl, batch or extract jobs by id.
    • Engines implementing the Engine trait must implement the budgeted search and extract methods to support those operations for accounts with a daily page quota; the default implementation rejects them.
  4. v1.2.12026-11-08 · 2026-11-08 04:48 UTC
    查看更新说明

    PageSift 1.2.1 Release Notes

    Release Version: v1.2.1 License: AGPL-3.0-only (Commercial licensing available)

    Changes since 1.2.0.


    Security

    • Identity-scoped API requests (owner set by an authenticated API caller) no longer read from or write to the shared result cache. Previously the cache key had no caller, egress or fingerprint dimension, so a page fetched with one API key's session cookies could be returned to another key. Anonymous requests keep the existing cache behavior.
    • The result cache is unchanged for requests without a caller identity. Per-owner session isolation in the identity pool is not affected.

    Fixed

    • A 503 response with Retry-After is now classified as throttled in the itna attempt trace and in egress-pool outcomes. The header was present in the response but never reached classify, so the trace said other while the classifier's contract said throttled. The status of the returned page does not change.
    • A 503 response without Retry-After is still classified as other.

    MCP

    • pagesift_crawl_status is renamed to pagesift_poll_job. The tool polls both crawl and batch scrape jobs, and the new name pairs with pagesift_cancel_job. There is no old-name alias. Migration: change the tool name in the client; arguments are unchanged.
    • New pagesift_cancel_job stops a running crawl or batch scrape job. Pages collected before the cancel stay available through pagesift_poll_job; work that finishes after the cancel is discarded. Cancelling an already finished job returns its current status, and an unknown or expired id is an error.
    • Every MCP tool now publishes an outputSchema with field descriptions for its structured result.
    • Input schemas now describe every parameter, including nested action, viewport, location, chunking and scrape-option fields, and document defaults, limits and sitemap enum values.
    • Tool descriptions state cache lifetime, keepSession lifetime, prompt-versus-actions usage, partial-failure behavior, polling and cancellation rules.
    • Read-only tools set idempotentHint: true; pagesift_cancel_job is idempotent and non-destructive.

    Compatibility

    • No configuration or data migration is required.
    • The MCP rename is a breaking change for clients that hard-code pagesift_crawl_status. No alias is kept because a duplicate tool would enter the tool set under two names.
    • HTTP APIs, the CLI, Python, Node and other language bindings are unchanged.

    Verification

    • Added engine tests for owner-scoped cache isolation (anonymous hit, owner bypass, no owner write-back) and for 503 with and without Retry-After.
    • Added MCP tests that every definition has an output schema and every input parameter has a description.
    • cargo fmt --check, git diff --check, the release identity check and the README checks pass.
  5. v1.2.02026-11-07 · 2026-11-07 01:15 UTC
    查看更新说明

    PageSift 1.2.0 Release Notes

    Release Version: v1.2.0 License: AGPL-3.0-only (Commercial licensing available)

    Changes since 1.1.3. Speed and quality figures in the README were measured on 1.1.0 and were not measured again for this release.


    Access-barrier recovery (opt-in)

    [itna] enabled = true adds a bounded recovery path for normal HTTP requests. It is off by default; with it off, the existing request path and configuration behave as before.

    • HTTP results are classified by status, response headers and the existing barrier rules.
    • A blocked or challenge HTTP result may get one browser retry on the same egress. Rate limits (429 and Retry-After), login walls and an explicit engine = "http" do not escalate.
    • Redirects and browser sub-requests draw from one network budget. When the budget is exhausted the request fails closed instead of continuing unbudgeted.
    • The attempt trace is reported in metadata.pagesift.itna or in the error details.

    Sessions and identities

    • Sessions are leased per owner, origin, egress and fingerprint. API requests with a stable caller identity can reuse a session across requests; anonymous requests receive a per-request session. Different owners never share a session.
    • 429 and 5xx responses, and cancellation, no longer count as identity failures. 401 and 403 still count.
    • Retired sessions are removed from the pool. A lease is released on cancellation as well as on success or failure.

    Fingerprint transport through proxies

    • browser_fingerprint can now be combined with an HTTP proxy (HTTP CONNECT), an HTTPS proxy, SOCKS5 or SOCKS5H.
    • Targets are resolved and SSRF-checked locally; the proxy receives an IP address, while TLS SNI and the HTTP authority keep the original hostname.
    • TLS and HTTP/2 still use the existing fingerprint-shaped transport. Proxy TLS certificates are verified.
    • A failed proxy or target tunnel is reported as an error. It is not silently downgraded to a plain reqwest request or a direct connection.
    • socks5h resolves targets locally, like socks5, because the target must pass the SSRF check before the tunnel opens.

    HTTP to browser handoff

    • Cookies from the HTTP session are imported into an isolated browser context only for the exact origin.
    • Imported cookies are host-only. Browsers do not isolate cookies by port, so same-host requests on another scheme or port are blocked, except the standard http:80 to https:443 upgrade. HTTPS to HTTP is blocked.
    • Path, Secure, HttpOnly and expiry are preserved. Imported cookies use SameSite=Strict because the session store does not keep SameSite.
    • The handoff is refused when the HTTP fingerprint's Chrome major version differs from the running browser's major version.

    Browser automation markers and challenges

    • When itna is enabled, the default launch arguments omit the Blink automation marker, and a document-start script clears navigator.webdriver for local and remote browsers. It does not fabricate hardware or identity.
    • Non-interactive JavaScript challenges get a bounded settle wait: at most 8 seconds and never beyond the request timeout.
    • Pages with interactive CAPTCHA widgets are not waited for. They return ACCESS_BARRIER with needsHuman: true. No CAPTCHA solver is included.

    Verification

    • Covered by local controlled fixtures in the release test suites for pagesift-itna, pagesift-net, pagesift-cdp, pagesift-policy, pagesift-engine and pagesift-api.
    • Local fixtures cover classification, attempt and network budgets, cancellation, proxy failure, certificate rejection, session isolation, cookie scope, automation-marker removal, non-interactive challenge settling and interactive-CAPTCHA reporting.
    • cargo fmt --check, git diff --check and cargo deny --config .github/deny.toml check pass.
    • No production-site or WAF pass-rate claims were measured for this release.

    Compatibility

    • No configuration or data migration is required. The `[itn

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    pagesift 1.2.2

    The web and document layer for AI agents: any URL, document, email, archive or source file in, clean Markdown or JSON out.
    One self-hosted Rust binary with a CLI, Firecrawl and Jina Reader APIs, an MCP server, and packages for Python, Node.js, Go, Java, C#, Ruby, PHP and more.

    Measured: PDF to Markdown 2.4 ms per page, 20.49× faster than the next best tool; HTML to Markdown 0.24 ms per page, 8.12× faster; main content 1.0 ms per page, 7.26× faster (lower is better); Office 91.7 files/s, 3.40× the next best (higher is better).

    License: AGPL-3.0 Commercial license Release crates.io PyPI npm PageSift MCP server – quality and maintenance score on Glama Discord

    English · 简体中文 · 日本語 · Español

    What it is

    pagesift reads the web and documents for software that thinks: it fetches a URL, rendering JavaScript only when that adds content, or opens a local file, and returns the content as Markdown or structured JSON. It covers single pages, whole sites, scanned PDFs, browser actions, change monitoring and research runs driven by your own model.

    Can replace or sit alongside: Firecrawl (same v1/v2 API, self-hosted), Jina Reader (/r/ and /s/), Crawl4AI, trafilatura, Readability, pymupdf4llm, Docling, Kreuzberg, xberg.

    At a glance

    • Input: URLs, HTML, PDF including scanned pages (OCR), image files (OCR), Word (.docx, .doc), Excel (.xlsx, .xlsb, .xls), PowerPoint (.pptx, .ppt), OpenDocument, RTF, WordPerfect, HWP, EPUB, MOBI, FB2, email (.eml, .mbox, .msg), archives (zip, tar, gz, bz2, xz, 7z), SQLite, dBASE, CSV, Markdown and other text formats, 373 source-code and config languages, WARC archives
    • Output: Markdown, HTML, raw HTML, links, images, metadata, schema-based JSON; warnings when a result is incomplete
    • Interfaces: CLI · Firecrawl v1/v2 HTTP API · Jina Reader · MCP (stdio or HTTP) · Python · Node.js / TypeScript · Rust crate · C ABI with Go, Java, Kotlin, C#, Ruby, PHP, Lua, Perl, Dart, Swift and Zig bindings · LangChain and LlamaIndex
    • Platforms: Linux x86_64 / aarch64 (glibc ≥ 2.28 and musl), macOS arm64, Windows x86_64; Docker image ghcr.io/yolow92/pagesift
    • Runtime: nothing to install for HTTP, PDF and Office. Optional: a browser for JavaScript pages, an NVIDIA GPU for OCR, your own model for /v2/agent
    • Memory: 18–377 MB peak per worker across the 1.1 benchmarks without a browser; OCR with formula models needs about 1.7 GB; capacity is sized from the cgroup limit
    • License: AGPL-3.0, or a commercial license
    • Latest: 1.2.2 · release notes

    Install and use

    InstallFirst call
    CLIcargo install pagesift --lockedpagesift scrape https://example.com
    Pythonpip install pagesiftpagesift.scrape("https://example.com").markdown
    Node.jsnpm install @pagesift/node(await new Scraper().scrape("https://example.com")).markdown
    Serverdocker run -p 3002:3002 ghcr.io/yolow92/pagesift:1.2.2curl localhost:3002/r/https://example.com
    MCP—claude mcp add pagesift -- pagesift mcp

    CLI

    pagesift scrape https://example.com                          # Markdown to stdout
    pagesift scrape report.pdf                                   # local PDF, Office, e-book, email, archive, image, code or WARC
    pagesift --ocr scrape scan.pdf                               # OCR scanned pages; models download on first use
    pagesift crawl https://docs.rs --limit 500 --out ./data/     # one file per page
    pagesift crawl https://www.example.edu --query "graduate admission" --adaptive
    pagesift extract --schema schema.json https://example.com    # JSON by CSS selectors, repaired when the page changes
    pagesift doctor                                              # check browsers, GPU and models
    

    Python

    import pagesift
    
    page = pagesift.scrape("https://example.com", formats=["markdown", "links"])
    print(page.markdown, page.metadata["title"], page.links)
    
    pages = pagesift.scrape_many(["https://example.com", "https://example.org"], concurrency=8)
    
    scanner = pagesift.Scraper(ocr=True)     # models download when the first scanned page arrives
    print(scanner.parse(open("scan.pdf", "rb").read(), "scan.pdf").markdown)
    

    Node.js / TypeScript

    import { Scraper } from '@pagesift/node'
    
    const scraper = new Scraper()
    const page = await scraper.scrape('https://example.com', { formats: ['markdown', 'links'] })
    console.log(page.markdown, page.metadata.title, page.links)
    
    const items = await scraper.scrapeMany(['https://example.com', 'https://example.org'], { concurrency: 4 })
    

    HTTP server

    docker run -d -p 3002:3002 -v pagesift-data:/data -e PAGESIFT_API_KEYS=sk-test ghcr.io/yolow92/pagesift:1.2.2
    
    curl -s localhost:3002/v2/scrape -H 'Authorization: Bearer sk-test' -H 'Content-Type: application/json' \
      -d '{"url":"https://example.com","formats":["markdown"]}'                        # Firecrawl API
    curl -s localhost:3002/r/https://example.com -H 'Authorization: Bearer sk-test'    # Jina Reader
    curl -s localhost:3002/v2/parse -H 'Authorization: Bearer sk-test' \
      -F [email protected] -F 'options={"formats":["markdown"]}'                        # file upload
    

    Firecrawl SDKs work by changing the API URL. Upload API · Jina headers

    MCP

    pagesift mcp                                                  # stdio, for one agent
    pagesift mcp http --port 3003                                 # one shared local service
    claude mcp add --scope user --transport http pagesift http://127.0.0.1:3003/mcp
    

    Tools: pagesift_scrape, pagesift_batch_scrape, pagesift_crawl, pagesift_poll_job, pagesift_cancel_job, pagesift_map, pagesift_interact, pagesift_interact_stop, and with a configured model pagesift_agent, pagesift_agent_status. Shared MCP service

    What it can do

    CapabilityWhat you getDocs
    Clean contentMain-content detection and Markdown that keeps headings, lists, tables, code and mathBenchmarks
    DocumentsOwn Rust readers for PDF, current and legacy Office, OpenDocument, e-books, email, archives, images, databases and text formats, including damaged files and CJK fontsUpload API
    OCRScanned PDF pages through PP-OCRv6 and display formulas through PP-FormulaNet, in pure Rust on CPU or NVIDIA GPUUpload API
    Structured extractionJSON by CSS selectors that are relocated when a site changes, or by a schema your model writes once and pagesift cachesExtraction
    Browser actionsClicks, typing and scrolling on the page, plus sessions you can keep working inInteract
    AgentPOST /v2/agent answers a question from the web with your own model, and checks each field against the page it came fromAgent API
    MonitoringScheduled checks that separate real changes from dates, counters and ads, with webhooksMonitor
    CrawlingSitemaps, query-focused crawls that stop when pages stop helping, trap handling, robots.txt and per-host limitsBenchmarks
    ArchivesWARC output on every crawl, and WARC files as input with no networkRelease notes
    OperationsMulti-server gateway, workers and standby; job persistence, durable webhooks, metrics, audit logArchitecture
    SafetyPrivate-network and DNS-rebinding guards, and every incomplete result reports a warningBot policy

    How /v2/agent answers a question

    flowchart LR
        Q[Question + schema] --> M[Your model plans one step]
        M --> T[pagesift runs it<br/>search, map, scrape, extract]
        T --> E[Text archived as evidence]
        E --> D{Enough?}
        D -->|no, budget left| M
        D -->|yes| A[Answer matched to the schema]
        A --> V[Each field checked<br/>against the evidence]
        V --> R[JSON + sources + warnings]
    

    robots.txt, rate limits and network guards apply to every page. The model chooses URLs and queries, not fetch options.

    Performance

    ↑ higher is better · ↓ lower is better. Strongest result per domain; methods and sources in the full report.

    TaskMetricPageSiftBest other toolGap
    PDF → Markdown — olmOCR-bench 1,269 pages, per page (single thread)ms/page ↓2.4pypdf 50.0×20.49
    PDF → Markdown — B1 144 pages, 1 worker, resident serverfiles/s ↑176.5pdf_oxide 100.6×1.75
    PDF → Markdown — olmOCR-bench 1,269 pagesofficial score ↑0.645pymupdf4llm 0.484+0.161
    HTML → Markdown — 600 generated documents, per pagems/page ↓0.24Turndown 1.9×8.12
    HTML → Markdown — 600 generated documents, fidelitymean F1 ↑1.000markdownify 0.936+0.064
    Main content — Firecrawl 597 pages, single threadp50 ms/page ↓1.0crw 7.4×7.26
    Main content — WCXB test split, 150 pagesF1 ↑0.866Readability + Turndown 0.848+0.018
    Publication dates — htmldate 1,000 pages, date searchms/page ↓0.31htmldate (fast) 2.0×6.45
    RAG chunking — 5 corpora, 1.4 MBtotal ms ↓7chonkie recursive 35×5.01
    Office / e-books — B4 81 files, in-processfiles/s ↑91.7xberg 27.0×3.40
    Office / e-books — B4 hold-out 39 files, structure keptstructure kept ↑0.988xberg 0.878+0.110
    RAG query filter — 472 questions, default settingsanswer recall ↑0.929Crawl4AI BM25 0.673+0.256
    Wild crawl — polite, 40 sites × 60 pages, coveragecoverage ↑0.740Crawl4AI (HTTP) 0.529+0.211
    Wild crawl — fast, 40 sites × 60 pages, coveragecoverage ↑0.687Crawl4AI (HTTP) 0.499+0.188
    Scanned PDFs — B5 134 pages, olmOCR score without baseline, OCR onolmOCR score ↑0.314Docling (GPU) 0.125+0.189
    Scanned PDFs — B5 134 pages, olmOCR score with baseline, OCR onolmOCR score ↑0.543Docling (GPU) 0.410+0.133
    Hard PDFs — B3 100 pdf.js files, completioncompletion ↑0.720pymupdf4llm 0.680+0.040
    Peak memory per workerPageSift MB ↓Other tool MBLess memory
    PDF, B1 pages32Docling (CPU) 3,675 (2026-10-28)×113.1
    HTML main content, A2 pages20Readability + Turndown 1,200 (2026-10-28)×60.8
    Crawl, 200 sites × 100 pages218spider 5,500 (2026-10-21)×25.2
    HTML main content, A2 pages20trafilatura 123 (2026-10-28)×6.2
    Office and e-books, B4 files47Kreuzberg 231 (2026-10-28)×4.9
    Crawl with browser, 200 sites × 100 pages669Google Chrome 2,300 (2026-10-21)×3.4
    PDF, B1 pages32Kreuzberg 76 (2026-10-28)×2.3
    JavaScript pages, A3 (live web)520Crawl4AI 982 (2026-10-28)×1.9

    PageSift 1.1 and xberg 1.3.9. xberg measured on 2026-11-04; a range is two runs. A bold value is the best in its row.

    MetricPageSift CLIPageSift serverxbergxberg layout mode
    PDF B1, olmOCR score 1,269 pages ↑0.645—0.4360.472
    Office B4, structure kept, hold-out 39 files ↑0.988—0.878—
    PDF B1, 1 worker, files/s ↑161.4176.529.5–29.91.35
    PDF B1, 16 workers, files/s ↑539.3305.165.8–68.41.41
    Office B4, 1 worker, files/s ↑91.769.127.0—
    Office B4, 16 workers, files/s ↑314.0147.073.4–74.2—
    PDF B1, 1 worker, peak MB ↓32211147–1721118
    Office B4, 1 worker, peak MB ↓47252112—
    Office B4, 1 worker, median ms per file ↓4.52.23.2–3.3—

    fast, 40 sites × 60 pages, time (spider covered about half as many pages) 16.1 seconds vs spider 1.4 seconds; A2 replay, 269 pages, HTTP only, no rate limit, 1 worker 47.5 pages/s vs spider 156.6 pages/s; A2 269 random pages, resident worker, per page 4.5 ms/page vs Resiliparse 2.1 ms/page.

    Full report

    Architecture

    The core is written from the file format up in Rust, and limits are measured at run time instead of being set by hand.

    flowchart TD
        CLI[CLI / Rust caller] --> Engine[pagesift-engine]
        HTTP[Firecrawl and Jina HTTP API] --> Engine
        Bindings[Python / Node / MCP / C ABI: Go, Java, C#, Ruby, PHP and more] --> Engine
        Engine --> Hooks[pagesift-hooks: rules and hooks]
        Hooks --> Policy[pagesift-policy: robots, rate limits, backoff, identity leases]
        Policy --> Net[pagesift-net: HTTP, SSRF guards, validated proxy tunnels, optional TLS fingerprint]
        Net --> Plan{pagesift-plan: render?}
        Plan -->|No| DOM[pagesift-html: arena DOM]
        Plan -->|Yes| CDP[pagesift-cdp: browser pool, automation-marker removal, challenge settle]
        CDP --> DOM
        Net -->|PDF| PDF[pagesift-pdf]
        Net -->|Office, e-books, email, archives, text| Office[pagesift-office]
        Net -->|Image| OCR[pagesift-ocr, pagesift-infer, pagesift-gpu]
        Office -->|archive member, attachment| Office
        Office -->|archive member, attachment| PDF
        Office -->|source code| Syntax[pagesift-syntax]
        PDF -->|scanned page| OCR
        DOM --> Content[pagesift-content: main content, Markdown, metadata]
        DOM --> Extract[pagesift-extract: selectors, relocation, chunking]
        PDF --> Sink[pagesift-sink: outputs and cache format]
        Office --> Sink
        OCR --> Sink
        Content --> Sink
        Extract --> Sink
        Engine --> Store[pagesift-store: cache, selector memory, records]
        Engine -.-> ITNA[pagesift-itna: barrier classification, attempt and network budgets]
        ITNA -.->|shared budget| Net
        ITNA -.->|one bounded fallback| CDP
        Net -.->|restricted cookie handoff| CDP
    

    Access-barrier recovery is opt-in ([itna] enabled, off by default). pagesift-itna classifies barriers, allows one bounded browser fallback, and shares one network budget across redirects and browser sub-requests. Sessions are leased per owner, origin, egress and fingerprint; HTTP cookies reach the browser only through an exact-origin handoff. Interactive CAPTCHAs are reported as needing a human and are not solved.

    Own code down to the format. Parsing runs in process with no Python, JVM or Node runtime behind it. pagesift has its own zero-copy HTML5 parser, PDF file layer with JPEG, CCITT and JBIG2 decoders, readers for Office, e-books, email and archives, neural network inference with GPU kernels compiled from Rust, Chrome DevTools client, MCP server and append-only store. A worker costs tens of megabytes, not a loaded interpreter, and starts in milliseconds.

    One worker per core. CPU work runs on resident workers grouped by NUMA node, which steal work inside their own node first. A single admission path covers CPU, memory and browser tabs, and capacity comes from the cgroup limit, so a container stays within its memory instead of being killed.

    Measured instead of fixed. Concurrency follows a Universal Scalability Law fit, per-host limits follow a latency gradient, stage timeouts use survival analysis and retries use per-class success rates. Each one starts from a safe default and moves only on statistically significant evidence (δ = 0.05). User settings and safety limits stay hard limits.

    A browser only when it pays. For each family of URL paths, pagesift learns whether rendering added content, and the rendered result is kept only if it scores higher. Page data such as __NEXT_DATA__ and JSON-LD is read without a browser. Lightpanda, moli and Chrome form a fallback chain, and --explain records every decision.

    Honest results. A partial page, a truncated file or a skipped scan returns a warning code instead of looking complete. Agent answers report which values were found in the evidence, and selector repairs report the old and new selector.

    From one binary to a fleet. serve --role gateway, worker and standby share the same binary, with site affinity by rendezvous hashing and leases with fencing. Jobs and webhooks resume after a restart.

    flowchart LR
        C[Clients] --> G[Gateway<br/>API, jobs, webhooks]
        G -->|same site, same worker| W1[Worker]
        G --> W2[Worker]
        G --> W3[Worker]
        G -.->|job records| S[Standby<br/>takes over on lease loss]
    

    Full architecture

    When to use it, and when not

    Good fit

    • Feeding web pages and documents to an LLM, a RAG index or an agent
    • Self-hosting a Firecrawl- or Jina Reader-style service with no per-page fees
    • Mixed input: the same call handles HTML, PDF, scans, Office files and e-books
    • Small machines and containers, where memory is bounded by the cgroup limit

    Pick something else when

    • Your input is image files. OCR covers scanned pages inside PDFs, not standalone images.
    • AGPL does not work for you and a commercial license is not an option.
    • You need a managed cloud service. pagesift is self-hosted.

    License

    AGPL-3.0. For proprietary linking or private deployment without AGPL obligations, see the commercial license or write to [email protected].

    What's new in 1.2.2

    Crawl, batch and extract jobs are restricted to their owner. Search and extract page attempts count against the daily quota, and cached pages are checked against robots.txt. Unsupported snapshot and base64-image options are now rejected instead of silently ignored.

    Release notes · 1.2.1 · all releases · CHANGELOG


    Community

    Questions or feedback: Discord · Issues · Discussions

    Citation

    @software{pagesift2026,
      title  = {PageSift: Rust Web and Document Extraction Engine for AI Pipelines},
      author = {YOLOW92},
      year   = {2026},
      url    = {https://github.com/YOLOW92/pagesift},
      note   = {Version 1.2.2}
    }
    

    Star History

    Star History Chart