<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ゴエンチョウ</title>
    <description>The latest articles on DEV Community by ゴエンチョウ (@yolow92).</description>
    <link>https://dev.to/yolow92</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4200665%2F387d48c4-1725-44b0-9568-73fc14cc0792.jpg</url>
      <title>DEV Community: ゴエンチョウ</title>
      <link>https://dev.to/yolow92</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yolow92"/>
    <language>en</language>
    <item>
      <title>I crawled the Tranco Top 100k with a Rust engine that never passed 188 MB of RAM</title>
      <dc:creator>ゴエンチョウ</dc:creator>
      <pubDate>Fri, 23 Oct 2026 13:34:32 +0000</pubDate>
      <link>https://dev.to/yolow92/i-crawled-the-tranco-top-100k-with-a-rust-engine-that-never-passed-188-mb-of-ram-4bij</link>
      <guid>https://dev.to/yolow92/i-crawled-the-tranco-top-100k-with-a-rust-engine-that-never-passed-188-mb-of-ram-4bij</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; I built &lt;a href="https://github.com/YOLOW92/pagesift" rel="noopener noreferrer"&gt;PageSift&lt;/a&gt;, a single-binary web scraping engine in Rust. It's Firecrawl v1/v2 API-compatible, turns pages into clean Markdown for LLM pipelines, and just hit v0.50.0. On a live crawl of the Tranco Top 100,000 domains, its peak memory stayed flat at &lt;strong&gt;188.4 MB&lt;/strong&gt; while Spider (also Rust) ballooned to &lt;strong&gt;~9.0 GB&lt;/strong&gt; and got OOM-killed. Benchmarks, raw data, and reproduction scripts are all in the repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built it
&lt;/h2&gt;

&lt;p&gt;I run a small AI product, and web scraping was the part that kept hurting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Self-hosted Firecrawl spins up 7 services by default and is AGPL.&lt;/li&gt;
&lt;li&gt;Crawl4AI is Python + Playwright + Node + Chromium — an 847 MB venv before you even start.&lt;/li&gt;
&lt;li&gt;Worst of all, captcha and interstitial pages kept landing in my database &lt;em&gt;as if they were content&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So PageSift is one binary. No Redis, no database, no message queue. And when a site blocks it, you get an honest &lt;code&gt;ACCESS_BARRIER&lt;/code&gt; error instead of a fake page.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 100k live test
&lt;/h2&gt;

&lt;p&gt;Setup: AMD EPYC server (32 cores, 128 GB RAM), Tranco Top 100k live domains, identical conditions for both engines — 768 async concurrency, 3.5 s connect / 10 s total timeout, Blake3 dedup, streaming Markdown extraction.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;PageSift 0.50&lt;/th&gt;
&lt;th&gt;Spider 2.53.9&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Peak RSS&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;188.4 MB (flat)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8,978.9 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Valid Markdown docs&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;60,659&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;59,803&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extraction conversion&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;96.38%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;82.82% (17.2% empty shells)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory behavior&lt;/td&gt;
&lt;td&gt;zero leaks&lt;/td&gt;
&lt;td&gt;leaked to 14 GB, OOM-killed at the 12 GB cap&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The full dataset and scripts: &lt;a href="https://github.com/YOLOW92/pagesift/blob/main/bench/results/final/BENCHMARK_100K_PAGESIFT_VS_SPIDER.md" rel="noopener noreferrer"&gt;&lt;code&gt;bench/results/final/BENCHMARK_100K_PAGESIFT_VS_SPIDER.md&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Extraction quality and speed
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Main-content extraction: &lt;strong&gt;0.85 ms/page (p50)&lt;/strong&gt;, F1 &lt;strong&gt;0.716&lt;/strong&gt; on Firecrawl's labelled dataset — crw 0.711, Crawl4AI 0.670. On a 545-page calibrated WebMainBench subset it beats Essence on average, and still &lt;strong&gt;loses on 117 pages&lt;/strong&gt;. Per-page scores are published; I'd rather show the losses than cherry-pick.&lt;/li&gt;
&lt;li&gt;PDF → Markdown: &lt;strong&gt;71.0&lt;/strong&gt; on olmOCR-bench, formulas recovered as LaTeX at &lt;strong&gt;44.3%&lt;/strong&gt; (pymupdf4llm: 0%), at &lt;strong&gt;3.4 ms/page&lt;/strong&gt; vs 320 ms.&lt;/li&gt;
&lt;li&gt;RAG: the BM25 query filter answers in &lt;strong&gt;1.35 ms/query&lt;/strong&gt;, keeping 93% of the answer text in ~1,150 words where Crawl4AI's filter keeps 67% in 13,500 words.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3002:3002 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;PAGESIFT_API_KEYS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;change-me ghcr.io/yolow92/pagesift:0.50.0

&lt;span class="c"&gt;# or&lt;/span&gt;
cargo &lt;span class="nb"&gt;install &lt;/span&gt;pagesift
pagesift serve   &lt;span class="c"&gt;# Firecrawl-compatible API on :3002&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pagesift&lt;/span&gt;

&lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pagesift&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scrape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's also a native Node package (&lt;code&gt;@pagesift/node&lt;/code&gt;), an MCP server for agents, and JS rendering that only fires when a page actually needs it (Lightpanda → moli → Chrome, chosen per host).&lt;/p&gt;

&lt;h2&gt;
  
  
  How it's fast
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;zero-copy HTML parser&lt;/strong&gt;: text and attribute values borrow from the source string; only entity-containing fragments get decoded.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Readability reimplementation&lt;/strong&gt; that scores paragraphs in a single pass over precomputed text statistics — no DOM mutation, no repeated length calculations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hand-written scanners instead of regexes&lt;/strong&gt; in the hot paths (class/id word classification is a compile-time &lt;code&gt;match&lt;/code&gt; with a stack buffer).&lt;/li&gt;
&lt;li&gt;The workspace is &lt;code&gt;forbid(unsafe_code)&lt;/code&gt; — with exactly one exception: a single &lt;code&gt;mallopt&lt;/code&gt; call that pins glibc's mmap threshold so page-sized buffers return to the OS instead of bloating RSS. That one call cut peak RSS in local crawl tests from 188 MB to ~75 MB.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  It plays by the rules
&lt;/h2&gt;

&lt;p&gt;PageSift respects &lt;code&gt;robots.txt&lt;/code&gt; and &lt;code&gt;Crawl-delay&lt;/code&gt;, rate-limits per host, uses an honest User-Agent, and does &lt;strong&gt;no&lt;/strong&gt; anti-bot bypassing: no TLS fingerprinting, no captcha solving, no proxy rotation. PRs adding stealth features are not accepted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;17 capability categories are still marked &lt;strong&gt;partial&lt;/strong&gt; in my own inventory — persistent browser interaction and autonomous agent workflows are explicitly out of scope.&lt;/li&gt;
&lt;li&gt;The license is &lt;strong&gt;AGPL-3.0 + a commercial option&lt;/strong&gt;. Fully open for self-hosting; closed-source products need the commercial license.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/YOLOW92/pagesift" rel="noopener noreferrer"&gt;https://github.com/YOLOW92/pagesift&lt;/a&gt; — docs in English, 中文， 日本語 and Español.&lt;/p&gt;

&lt;p&gt;If you run Firecrawl or Crawl4AI in production, I'd genuinely like to know: what breaks first for you?&lt;/p&gt;

</description>
      <category>rust</category>
      <category>opensource</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
