The big captcha_solver.py (6 providers: capsolver/2captcha/anti-captcha/ capmonster/deathbycaptcha/nextcaptcha, supports reCAPTCHA v2/v3, hCaptcha, Turnstile, image) was an orphan module — never imported. The /v1/auth/captcha endpoint was using the smaller auth_connector.solve_captcha (2 providers, 2captcha stubbed out). This commit: - Replaces the /v1/auth/captcha handler to delegate to CaptchaSolver - Adds support for captcha_type: recaptcha_v2, recaptcha_v3, hcaptcha, image - Adds per-provider api_keys dict for the 6-provider chain - Adds tests/test_captcha_solver_wiring.py - Annotates account_manager.py and signup_automator.py (BSL-licensed) with notes about their unwired status and where they belong in the architecture The two remaining orphan modules are kept (not deleted) because they are BSL 1.1 stealth code that may be wired in the future as anti-fingerprint or identity-evasion routes. See FEATURES.md and ARCHITECTURE.md. Audit item 10. Tests: 623 passed, 1 skipped (test_ready_returns_200 fails pre-existing because Ollama is unreachable from test env). |
||
|---|---|---|
| .actor | ||
| .forgejo | ||
| .github | ||
| alembic | ||
| browser-extension | ||
| docs/adr | ||
| llm_providers | ||
| pry_mcp | ||
| routers | ||
| shopify-app | ||
| stealth_scripts | ||
| templates | ||
| tests | ||
| wordpress-plugin | ||
| workers | ||
| .commitlintrc.yml | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| .pre-commit-config.yaml | ||
| .secretsallow | ||
| account_manager.py | ||
| actor_marketplace.py | ||
| adaptive.py | ||
| advanced.py | ||
| agency.py | ||
| AGENTS.md | ||
| ai_plugin.py | ||
| alembic.ini | ||
| alerter.py | ||
| anomaly.py | ||
| api.py | ||
| apify_actor.py | ||
| apify_schema.py | ||
| ARCHITECTURE.md | ||
| AUDIT.md | ||
| auth.py | ||
| auth_connector.py | ||
| automator.py | ||
| behavioral_biometrics.py | ||
| browser_pool.py | ||
| cache.py | ||
| camoufox_integration.py | ||
| captcha_solver.py | ||
| cli.py | ||
| client.py | ||
| commerce_sync.py | ||
| compliance.py | ||
| cookie_warmer.py | ||
| costing.py | ||
| crm_sync.py | ||
| db.py | ||
| DECISIONS.md | ||
| dedup.py | ||
| DEPLOYMENT.md | ||
| deps.py | ||
| destinations.py | ||
| DEVELOPMENT.md | ||
| docker-compose.yml | ||
| docker-entrypoint.sh | ||
| Dockerfile | ||
| Dockerfile.apify | ||
| email_scraper.py | ||
| enrichment.py | ||
| errors.py | ||
| extraction.py | ||
| extractor.py | ||
| FEATURES.md | ||
| freshness.py | ||
| gdpr.py | ||
| gdpr_real.py | ||
| glama.json | ||
| graphql_discovery.py | ||
| intelligence.py | ||
| jobqueue.py | ||
| lazy_load.py | ||
| LICENSE | ||
| LICENSE-BSL-STEALTH | ||
| LICENSING_PRICING_STRATEGY.md | ||
| llm_features.py | ||
| logging_config.py | ||
| Makefile | ||
| markdown_gen.py | ||
| mcp_production.py | ||
| mcp_server.py | ||
| mcp_sse.py | ||
| MCP_X402_AUDIT.md | ||
| monitor.py | ||
| network.py | ||
| observability.py | ||
| ocr_extractor.py | ||
| openapi.json | ||
| parser.py | ||
| paths.py | ||
| pdf_extractor.py | ||
| pipeline.py | ||
| pipelines.py | ||
| PLAN.md | ||
| proxy_manager.py | ||
| proxy_referrals.py | ||
| pry_sdk.py | ||
| pryextras.py | ||
| pryfile.py | ||
| pulsemcp.json | ||
| pyproject.toml | ||
| quality.py | ||
| ratelimit.py | ||
| README.md | ||
| reconciliation.py | ||
| referrals.py | ||
| reports.py | ||
| reports_real.py | ||
| requirements.lock | ||
| requirements.txt | ||
| resilience.py | ||
| retry.py | ||
| review.py | ||
| ROADMAP.md | ||
| schema_extraction.py | ||
| scraper.py | ||
| secrets_backend.py | ||
| SECURITY.md | ||
| seo_monitor.py | ||
| sessions.py | ||
| settings.py | ||
| shadow_dom.py | ||
| signup_automator.py | ||
| smithery.yaml | ||
| STATUS.md | ||
| stealth_engine.py | ||
| structure_monitor.py | ||
| tasks.py | ||
| template_engine.py | ||
| test.sh | ||
| TESTING.md | ||
| tls_fingerprint.py | ||
| training_data.py | ||
| ultimate_scraper.py | ||
| url_guard.py | ||
| USAGE.md | ||
| webhook_delivery.py | ||
| websocket_scraper.py | ||
| wrangler.toml | ||
| x402.py | ||
| x402_middleware.py | ||
//: # (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 (recommended)
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