Skip to main content

mudfish

Python bindings for Mudfish Crawler, a Rust-native web crawling and intelligence engine.

This package wraps the Rust crawl engine directly (via PyO3) — there is no subprocess or network hop to a separate server. It exposes a typed, Pythonic API over the engine; the Rust project itself is at an early stage (see the main repo's ROADMAP_HONEST.md for full status).

Install

pip install mudfish

Usage

import mudfish

result = mudfish.crawl("https://example.com", depth=2, concurrency=30)

print(result.stats.urls_fetched, result.stats.duration_secs)
for page in result:                          # CrawlResult is iterable over its pages
    print(page.status_code, page.url, page.title)

crawl() blocks until the crawl finishes (or hits max_urls / max_duration_secs) and returns a typed CrawlResult:

Object Fields
CrawlResult crawl_id, pages: list[Page], errors: list[CrawlError], stats: CrawlStats — iterable over pages, len() is the page count, plus ok_pages
Page url, final_url, status_code, content_type, depth, metadata: PageMetadata, links: list[Link], body_bytes, fetched_via: FetchMethod — helpers title, is_ok
PageMetadata title, meta_description, canonical
Link url, anchor_text, rel
CrawlError url, message
CrawlStats urls_discovered, urls_fetched, urls_skipped, errors, bytes_downloaded, duration_ms — helpers duration_secs, throughput_per_sec
FetchMethod FetchMethod.HTTP ("Http") / FetchMethod.BROWSER ("Browser")

Every typed object also supports the raw engine dict shape (result["stats"], page["status_code"], page.to_dict()), so code written against earlier versions keeps working. If you only want the raw dict, use mudfish.crawl_dict(...).

Async

crawl_async() runs the blocking engine on a worker thread, so it composes with asyncio and several crawls can run concurrently:

import asyncio
import mudfish

async def main() -> None:
    results = await asyncio.gather(
        mudfish.crawl_async("https://a.example"),
        mudfish.crawl_async("https://b.example"),
    )
    for result in results:
        print(result.stats.urls_fetched)

asyncio.run(main())

Reusable configuration

crawler = mudfish.Crawler(depth=1, concurrency=10)
home = crawler.crawl("https://example.com")
blog = await crawler.crawl_async("https://example.com/blog")

Errors

try:
    mudfish.crawl("not-a-url")
except mudfish.InvalidURLError:      # also a ValueError
    ...
except mudfish.CrawlFailedError:     # also a RuntimeError
    ...

Everything derives from mudfish.MudfishError.

Options

All keyword-only, matching the CLI's flags (also available as the CrawlOptions dataclass):

Parameter Default Meaning
depth 3 Max link-following depth
concurrency 50 Max requests in flight, whole crawl
per_host_concurrency 4 Max requests in flight per host
same_domain True Restrict crawl to the seed's resolved domain
max_urls 10000 Hard cap on URLs fetched
max_duration_secs None Optional wall-clock budget
timeout_secs 30 Per-request timeout
request_delay_ms 0 Min delay between requests to the same host
max_response_bytes 20 MB Per-response size cap
respect_robots True Honor robots.txt
allow_private_networks False Permit loopback/private targets (internal use only)
render_js False Re-render JS-dependent pages in headless Chrome (needs Chrome on the host; much slower)
render_settle_ms 2000 When render_js is on, settle time before capturing a rendered page
proxies () Proxy URLs to route requests through; supply several to rotate a pool
proxy_rotate_after 50 Requests through a proxy before rotating to the next
chrome_path None Explicit Chrome/chrome-headless-shell binary for render_js; defaults to the bundled binary, then host autodetection

Limitations

  • Chrome is not bundled in the PyPI wheel. With render_js=True the engine drives a headless Chrome that must already be installed on the host; if it cannot be launched, the crawl logs a warning and falls back to static HTML. A separate bundled wheel that ships a chrome-headless-shell (so render_js works with no host install) is attached to the GitHub release for each version — look for the asset named mudfish-<version>+chrome-*.whl.
  • Single-platform wheels initially. Built and published from the maintainer's machine, not a cross-platform CI matrix yet — check PyPI for which platforms have wheels; others will need a Rust toolchain to build from source.

Bundled-Chrome builds

To build the bundled wheel locally:

python3 tools/fetch_chrome_headless_shell.py   # pins + downloads chrome-headless-shell
cd crates/python && maturin build --release

The binary is fetched (never committed) into python/mudfish/_chrome/, the wheel picks it up automatically, and at runtime mudfish.bundled_chrome_path() returns it (overridable with MUDFISH_CHROME).

License

Apache-2.0.

Metadata

Release files for mudfish 0.2.4

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

Source distribution (sdist)

Source distribution for mudfish 0.2.4
File Size Uploaded
mudfish-0.2.4.tar.gz 94.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mudfish 0.2.4
File Interpreter ABI Platform
mudfish-0.2.4-cp39-abi3-macosx_11_0_arm64.whl CPython 3.9 abi3 macOS 11.0+ ARM64 Details

Total release size: 104.2 MB

Release files / mudfish-0.2.4.tar.gz

Download URL mudfish-0.2.4.tar.gz
Size 94.3 kB
Tags Source
SHA-256 checksum
How to use checksums
3ac7f4cc6a2569542ed423f49974510ed09ba09ab3e6bf8d3a79571b52d70c38
BLAKE2b-256 checksum
How to use checksums
684ac52d435714e0704143c0d0df7c8e24f36e620e144aff437739c30657fc7a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.6

Release files / mudfish-0.2.4-cp39-abi3-macosx_11_0_arm64.whl

Download URL mudfish-0.2.4-cp39-abi3-macosx_11_0_arm64.whl
Size 104.1 MB
Tags CPython 3.9 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
8c475f17a19a3bd9f3d0c021596184824244c6ef9efa10671764fffa26d04c65
BLAKE2b-256 checksum
How to use checksums
f8b0a77b65e0666ef227afa537ced63aecc9aa984a2d26a9a4a48ee53682e949
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.6

Release history Release notifications | RSS feed

This release

0.2.4 This release

2 release files

0.2.3

9 release files

0.2.2

9 release files

0.2.1

9 release files

0.2.0

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