PryScraper — multi-source crypto intelligence crawler. FastAPI + Docker. CLI + MCP server + SDK (munchcrawl_sdk.py). Scraper, extractor, parser, automator, job queue. Referral proxy rotation. Closed-source.
Find a file
cryptorugmunch 00db352faa refactor(api): split Auth endpoints into routers/auth.py (127 lines)
This is the first split of api.py (4,668 lines) into a routers/
package, one router per OpenAPI tag. This commit demonstrates the
pattern by splitting just the Auth tag (6 endpoints, 127 lines in
the new file). The remaining 51 tags can be split in subsequent
commits, one router per commit.

The full split is a multi-hour refactor; this commit sets up the
infrastructure (routers/__init__.py, the include_router pattern,
the SPDX headers) so future splits are mechanical.

Changes:
- New package routers/
  - __init__.py (45 lines, package docstring, migration order)
  - auth.py (127 lines, 6 endpoints, all behavior identical to
    the inline versions that were in api.py)
- api.py: removed the 6 inline Auth endpoint definitions, replaced
  with a single `app.include_router(auth_router)` call
- api.py LOC: 4,668 -> 4,627 (-41 lines)
- Total FastAPI routes: 197 -> 192 (the 6 inline removed, 1
  _IncludedRouter placeholder added; 5 unique paths in OpenAPI
  spec - same as before, since GET+POST share a path)
- All routes registered, all behavior preserved
- Tests: 436/437 pass (1 pre-existing SSE sandbox failure, unrelated)

The pattern for future commits:
  1. Read a tag's endpoints from api.py
  2. Create routers/<tag>.py with the same code, but using a
     local `router = APIRouter(tags=["<Tag>"])` instead of
     `@app.post(..., tags=["<Tag>"])`
  3. Replace the inline section in api.py with
     `from routers.<tag> import router as <tag>_router`
     `app.include_router(<tag>_router)`
  4. Commit

Suggested commit order (smallest first, to spread risk):
  - health (3 endpoints, ~50 lines)
  - stats (1 endpoint, ~30 lines)
  - costing (4 endpoints, ~150 lines)
  - freshness (3 endpoints, ~100 lines)
  - structure (3 endpoints, ~120 lines)
  - seo (3 endpoints, ~120 lines)
  - compliance (2 endpoints, ~200 lines)
  - gdpr (8 endpoints, ~300 lines)
  - sessions (5 endpoints, ~200 lines)
  - monitoring (5 endpoints, ~250 lines)
  - intelligence (4 endpoints, ~300 lines)
  - scraping (8 endpoints, ~400 lines)
  - extraction (8 endpoints, ~400 lines)
  - advanced (16 endpoints, ~700 lines - needs to be split further)

When all routers are split, api.py will be ~500 lines (the
lifespan, models, helpers, app definition, and include_router
calls), well under the 500-line per-file rule.
2026-07-02 21:17:40 +02:00
.forgejo ci: add gitleaks + bandit jobs; split single job into lint/typecheck/test/secrets/security 2026-07-02 20:02:06 +02:00
.github chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
browser-extension chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
docs/adr chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
llm_providers refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
routers refactor(api): split Auth endpoints into routers/auth.py (127 lines) 2026-07-02 21:17:40 +02:00
shopify-app chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
stealth_scripts chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
templates refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
tests feat(db): SQLAlchemy foundation with 24 models + JSON importer 2026-07-02 21:10:46 +02:00
wordpress-plugin chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
workers chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
.dockerignore docs: apply fleet-template (16-artifact scaffold) 2026-07-02 02:07:13 +07:00
.env.example feat(secrets): gopass-based secret backend (PRY_SECRET_BACKEND) 2026-07-02 20:26:00 +02:00
.gitignore docs: apply fleet-template (16-artifact scaffold) 2026-07-02 02:07:13 +07:00
.pre-commit-config.yaml chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
.secretsallow docs: apply fleet-template (16-artifact scaffold) 2026-07-02 02:07:13 +07:00
account_manager.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
actor_marketplace.py refactor(paths): replace 26 modules hardcoded ~/.pry/ with PRY_DATA_DIR 2026-07-02 20:20:04 +02:00
adaptive.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
advanced.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
agency.py feat(logging): add structlog + JSON logging (CONVENTIONS.md Part 5) 2026-07-02 20:55:41 +02:00
AGENTS.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
ai_plugin.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
alerter.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
anomaly.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
api.py refactor(api): split Auth endpoints into routers/auth.py (127 lines) 2026-07-02 21:17:40 +02:00
ARCHITECTURE.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
AUDIT.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
auth.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
auth_connector.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
automator.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
behavioral_biometrics.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
browser_pool.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
cache.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
camoufox_integration.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
captcha_solver.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
cli.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
client.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
commerce_sync.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
compliance.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
config.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
cookie_warmer.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
costing.py refactor(paths): replace 26 modules hardcoded ~/.pry/ with PRY_DATA_DIR 2026-07-02 20:20:04 +02:00
crm_sync.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
db.py feat(db): SQLAlchemy foundation with 24 models + JSON importer 2026-07-02 21:10:46 +02:00
DECISIONS.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
dedup.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
DEPLOYMENT.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
destinations.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
DEVELOPMENT.md feat(logging): add structlog + JSON logging (CONVENTIONS.md Part 5) 2026-07-02 20:55:41 +02:00
docker-compose.yml chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
Dockerfile docs: apply fleet-template (16-artifact scaffold) 2026-07-02 02:07:13 +07:00
email_scraper.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
enrichment.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
errors.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
extraction.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
extractor.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
FEATURES.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
freshness.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
gdpr.py refactor(paths): replace 26 modules hardcoded ~/.pry/ with PRY_DATA_DIR 2026-07-02 20:20:04 +02:00
gdpr_real.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
glama.json chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
graphql_discovery.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
intelligence.py refactor(paths): replace 26 modules hardcoded ~/.pry/ with PRY_DATA_DIR 2026-07-02 20:20:04 +02:00
jobqueue.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
lazy_load.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
LICENSE chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
LICENSE-BSL-STEALTH chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
LICENSING_PRICING_STRATEGY.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
llm_features.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
logging_config.py feat(logging): add structlog + JSON logging (CONVENTIONS.md Part 5) 2026-07-02 20:55:41 +02:00
Makefile docs: apply fleet-template (16-artifact scaffold) 2026-07-02 02:07:13 +07:00
markdown_gen.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
mconfig.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
mcp_production.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
mcp_server.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
mcp_sse.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
MCP_X402_AUDIT.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
monitor.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
network.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
observability.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
ocr_extractor.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
openapi.json fix(docs): regenerate openapi.json from running app 2026-07-02 20:00:26 +02:00
parser.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
paths.py refactor(paths): centralize ~/.pry/ into PRY_DATA_DIR env var 2026-07-02 20:19:46 +02:00
pdf_extractor.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
pipeline.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
pipelines.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
PLAN.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
proxy_manager.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
proxy_referrals.py feat(proxy): sync proxy_referrals.py from deploy; expose via API 2026-07-02 20:07:06 +02:00
pry_sdk.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
pryextras.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
pryfile.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
pulsemcp.json chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
pyproject.toml feat(db): SQLAlchemy foundation with 24 models + JSON importer 2026-07-02 21:10:46 +02:00
quality.py refactor(paths): replace 26 modules hardcoded ~/.pry/ with PRY_DATA_DIR 2026-07-02 20:20:04 +02:00
ratelimit.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
README.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
reconciliation.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
referrals.py refactor(paths): replace 26 modules hardcoded ~/.pry/ with PRY_DATA_DIR 2026-07-02 20:20:04 +02:00
reports.py refactor(paths): replace 26 modules hardcoded ~/.pry/ with PRY_DATA_DIR 2026-07-02 20:20:04 +02:00
reports_real.py refactor(paths): replace 26 modules hardcoded ~/.pry/ with PRY_DATA_DIR 2026-07-02 20:20:04 +02:00
requirements.txt chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
review.py refactor(paths): replace 26 modules hardcoded ~/.pry/ with PRY_DATA_DIR 2026-07-02 20:20:04 +02:00
ROADMAP.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
schema_extraction.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
scraper.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
secrets_backend.py feat(secrets): gopass-based secret backend (PRY_SECRET_BACKEND) 2026-07-02 20:26:00 +02:00
SECURITY.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
seo_monitor.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
sessions.py refactor(paths): replace 26 modules hardcoded ~/.pry/ with PRY_DATA_DIR 2026-07-02 20:20:04 +02:00
settings.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
shadow_dom.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
signup_automator.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
smithery.yaml chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
STATUS.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
stealth_engine.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
structure_monitor.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
tasks.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
template_engine.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
test.sh chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
TESTING.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
tls_fingerprint.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
training_data.py refactor(paths): replace 26 modules hardcoded ~/.pry/ with PRY_DATA_DIR 2026-07-02 20:20:04 +02:00
ultimate_scraper.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
USAGE.md chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
webhook_delivery.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
websocket_scraper.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
wrangler.toml chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00
x402.py refactor(exceptions): add ruff BLE001; convert 103 broad except Exception 2026-07-02 21:04:53 +02:00
x402_middleware.py chore(license): re-license to dual MIT (core) + BSL 1.1 (stealth) 2026-07-02 19:59:18 +02:00

//: # (Copyright (c) 2026 Rug Munch Media LLC)

Pry — Open any website

Self-hosted web scraping + browser automation API. Cloudflare bypass, document parsing, AI summarization. No API keys needed.

Quickstart

# Install
pip install pry

# Start the server
pry serve

# Scrape a URL
pry open https://example.com

# With JSON extraction
pry open https://store.com/product --json --schema product.json

# Crawl a site
pry crawl https://docs.com --max-pages 20 -o data.json

Docker

docker compose up -d
# Pry on :8002, FlareSolverr on :8191

CLI Reference

Command Description
pry open <url> Scrape URL to clean markdown
pry watch <url> Monitor page for changes
pry crawl <url> Crawl multiple pages
pry batch <file> Batch scrape URLs from file
pry parse <url> Parse PDF/DOCX/image
pry ss <url> Take screenshot
pry run [pry.yml] Execute job file
pry serve Start API server

API

POST /v1/scrape

{"url": "https://example.com", "bypassCloudflare": true, "formats": ["markdown"]}

POST /v1/crawl

{"url": "https://docs.com", "maxPages": 10, "maxDepth": 2}

POST /v1/automate

{"steps": [{"action": "navigate", "url": "https://...", {"action": "click", "selector": "#btn"}]]}

POST /v1/vision

Analyze images with free OpenRouter vision models. Auto-fallback across 5 models.

{"url": "https://...", "question": "What is shown?"}

POST /v1/extract

Extract structured data with JSON schema + optional AI fallback.

POST /v1/batch

Scrape up to 50 URLs in parallel.

POST /v1/compare

Diff two URLs.

POST /v1/summarize

AI summarization via local Ollama (free, private).

GET /health

Service health + cache stats + active sessions.

Python SDK

    from pry_sdk import PryCrawl

mc = PryCrawl("http://localhost:8002")
result = await mc.scrape("https://example.com")
print(result["data"]["markdown"])
    from pry_sdk import PryCrawlSync

mc = PryCrawlSync("http://localhost:8002")
result = mc.scrape("https://example.com")

SDK Methods

Method Description
scrape(url, **opts) Scrape to markdown
scrape_json(url, schema, **opts) Scrape with JSON extraction
crawl(url, max_pages, **opts) Crawl site
map(url, limit) Discover URLs
parse(url) Parse document
automate(steps, **opts) Browser automation
screenshot(url) Screenshot page
health() Service health

MCP (AI Agent Integration)

POST /mcp/call
{"name": "pry_scrape", "arguments": {"url": "https://..."}}

Compatible with Claude, Hermes, Cursor, and any MCP client.

Features

  • 4-tier anti-detection: Direct → FlareSolverr → Playwright → Googlebot
  • Cloudflare bypass: Automatic via FlareSolverr
  • Document parsing: PDF, DOCX, images (OCR), CSV, JSON
  • Browser automation: Login flows, form filling, sessions
  • Vision AI: Free OpenRouter vision models with auto-fallback
  • Diff tracking: Page change monitoring with webhooks
  • Batch processing: Parallel scrape with templates
  • SEO analysis: Title, meta, headings, keywords, readability
  • Schema extraction: JSON-LD, Open Graph, microdata
  • Export formats: JSON, CSV, RSS, TXT, SQL
  • Rate limiting: Per-IP token bucket (default 120 RPM)
  • Caching: LRU + Redis with TTL-based invalidation
  • WebSocket streaming: Real-time job progress
  • Circuit breaker: Per-domain backoff on failures

Architecture

┌─────────────┐  ┌──────────────┐  ┌──────────┐
│   Client    │→ │  Pry API     │→ │ Scraper  │
│ (CLI/SDK)   │  │  (FastAPI)   │  │  Engine  │
└─────────────┘  └──────┬───────┘  └────┬─────┘
                        │               ├─ Direct HTTP
                        │               ├─ FlareSolverr
                        │               ├─ Playwright
                        │               └─ Googlebot
                        │
                   ┌────┴────┐
                   │ Cache   │
                   │ Redis   │
                   │ Rate    │
                   └─────────┘

Deployment

docker compose up -d

Bare metal

pip install pry
playwright install chromium
# Optional: docker run -d -p 8191:8191 ghcr.io/flaresolverr/flaresolverr
pry serve

Environment

Variable Default Description
PRY_URL http://localhost:8005 API endpoint for CLI
TOR_ENABLED false Enable Tor routing
PROXY_URL HTTP/SOCKS proxy URL
RATE_LIMIT_RPM 120 Requests per minute
OPENROUTER_API_KEY For vision endpoint

Development

make install      # Install with dev deps
make dev          # Start hot-reload server
make lint         # ruff check
make format       # ruff format
make typecheck    # mypy
make test         # pytest
make check        # Full audit

License

Pry is dual-licensed to balance community openness with the protection of its advanced anti-detection and stealth capabilities.

  • Most code (core functionality, utilities, and standard modules) is licensed under the MIT License. This permissive license encourages community contributions and wide adoption. See LICENSE.

  • The anti-detection / stealth module is licensed under the BSL 1.1 (Business Source License). This module is free to use for non-production purposes; a commercial license is required for any production use. See LICENSE-BSL-STEALTH.

Additional Use Grant

Under the BSL 1.1, an Additional Use Grant permits free use of the stealth module for:

  • Personal, non-commercial projects
  • Non-production testing and evaluation
  • Academic research
  • Non-commercial open source software development
  • A 90-day evaluation period for any other purpose

For commercial licensing (production use, enterprise deployment, or embedding in proprietary products), please contact: enterprise@rugmunch.io