CrawlSage 0.1.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package CrawlSage --version 0.1.0
                    
NuGet\Install-Package CrawlSage -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CrawlSage" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CrawlSage" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="CrawlSage" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CrawlSage --version 0.1.0
                    
#r "nuget: CrawlSage, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CrawlSage@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CrawlSage&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=CrawlSage&version=0.1.0
                    
Install as a Cake Tool

CrawlSage

An F#-first web crawling & scraping framework for .NET.

CI Docs NuGet License: MIT Status .NET

CrawlSage — scrape a list and write a CSV in one command


What it is

CrawlSage is a web crawling and scraping framework designed around F# idioms — records and discriminated unions for data, option over null, and |> pipelines for behaviour. It pairs a full crawl engine (request queue, dedup, scheduler, item pipelines) with a resilient downloader, a concise HTML selector DSL, and first-class politeness.

Two principles shape it:

  • Don't render — extract. Most "dynamic" pages ship their data as embedded JSON. CrawlSage lifts that state directly, so the core needs no browser.
  • Polite by default. robots.txt, per-host pacing, retries and back-off are built into the engine, not bolted on.

Features

  • Resilient downloader — retry with back-off + jitter, per-request timeout, concurrency throttling, and gzip/brotli decompression, composed as wrappers around one HttpClient.
  • Parsing & links — forgiving, option-returning CSS selectors, plus a link extractor and URL canonicalisation for dedup and same-host filtering.
  • Spider engine — a frontier-driven scheduler with dedup, depth bounding, an item pipeline, per-page fault tolerance, and a CrawlEvent hook for stats / logging.
  • Resumable & bounded crawls — swap the frontier for a disk-backed one (resume after a stop or crash) or a memory-capped one, with zero engine changes.
  • Dynamic data, no browser — pull __NEXT_DATA__, JSON-LD and object/array globals out of the page, or replay the JSON API; an opt-in CrawlSage.Browser (Playwright) adapter renders the rest.
  • Politeness & rotationrobots.txt (per-host cache + Crawl-delay), per-host pacing, honest User-Agent / proxy rotation, and sitemap.xml discovery.
  • Sessions — a cookie-jar session for form login, saved and restored across runs.
  • Output — JSON / JSON Lines / CSV / data-frame sinks for items, plus binary file downloads.

Status

🚧 Early development. The framework (phases 0–8) is in place — resilient downloader, parsing DSL, spider engine, extraction, export, crawl ops, a sample cookbook and a tag-driven NuGet release — plus a hardening pass: link extraction, binary downloads, resumable/bounded frontiers, crawl stats, sessions, sitemaps and an opt-in browser renderer.


Install

dotnet add package CrawlSage

Quick start

# Requires the .NET 10 SDK
dotnet build CrawlSage.slnx
dotnet test  CrawlSage.slnx

A minimal fetch:

open CrawlSage

let body =
    Request.create "https://example.com"
    |> Request.withHeader "Accept-Language" "en"
    |> Http.fetch
    |> Async.RunSynchronously

printfn "%d — %d bytes" body.StatusCode body.Body.Length

Pull a list of fields with the selector DSL:

open CrawlSage

let authors =
    Http.getString "https://quotes.toscrape.com/"
    |> Async.RunSynchronously
    |> Html.parse
    |> Html.selectAll ".quote .author"
    |> List.map Html.text

Full crawlers — extract a list, follow pagination, lift embedded JSON, rotate User-Agents — are runnable under samples/, each polite by default.

Detailed usage: the Guide documents the full API, module by module — Http, Html, Extract, Spider, Session, Frontier, and the rest.


Project layout

CrawlSage/
├── src/CrawlSage/            # the framework library (browser-free core)
│   ├── Types.fs              #   Request / Response / Renderer / Sink
│   ├── Url.fs                #   resolve · canonicalise · same-host
│   ├── Http.fs               #   the downloader (shared HttpClient, gzip, bytes/download)
│   ├── Resilience.fs         #   retry · back-off · timeout · throttle
│   ├── Rotation.fs           #   honest UA & proxy rotation
│   ├── Session.fs            #   cookie-jar session (login, save/load)
│   ├── Html.fs               #   CSS selector DSL + link extraction
│   ├── Extract.fs            #   embedded-state / JSON extraction (no browser)
│   ├── Robots.fs             #   robots.txt parse · per-host cache · per-host pacing
│   ├── Sitemap.fs            #   sitemap.xml / sitemapindex discovery
│   ├── Frontier.fs           #   in-memory · bounded · persistent (resumable) frontier
│   ├── Spider.fs             #   crawl engine (frontier · dedup · depth · pipeline · stats)
│   └── Export.fs             #   sinks: JSON / JSONL / CSV / data frames + saveBytes
├── src/CrawlSage.Browser/    # opt-in JS renderer (Playwright) — not a core dependency
├── tests/                    # xUnit test projects (core + browser)
├── samples/                  # runnable, self-contained crawlers
└── docs/                     # documentation site

License

MIT.

Please crawl responsibly. Respect robots.txt, rate limits, a site's Terms of Service, and applicable law. CrawlSage is a tool; how you use it is your responsibility.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on CrawlSage:

Package Downloads
CrawlSage.Browser

Opt-in Playwright-backed browser renderer for CrawlSage — renders client-side pages the browser-free core can't, behind the same Renderer seam.

CrawlSage.Extensions

Opt-in Microsoft.Extensions integration for CrawlSage — bridge crawl events to ILogger and resolve an IHttpClientFactory-backed renderer via dependency injection (services.AddCrawlSage()).

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.0 140 6/26/2026
0.1.2 124 6/23/2026
0.1.1 102 6/21/2026
0.1.0 118 6/20/2026 0.1.0 is deprecated because it is no longer maintained.

Framework core through Phase 7: resilient downloader, HTML parsing DSL, spider engine, embedded-JSON extraction, export sinks, robots.txt + per-host pacing, UA/proxy rotation, and a runnable sample cookbook.