stygian-proxy
High-performance, resilient proxy rotation for the Stygian scraping ecosystem.
Features
| Feature | Description | Default |
|---|---|---|
| Rotation strategies | Round-robin, random, weighted, least-used | ✓ |
| Circuit breakers | Per-proxy failure tracking & recovery | ✓ |
| Health checking | Background async health prober | ✓ |
| RAII proxy handles | Automatic success/failure recording on drop | ✓ |
socks |
SOCKS4/5 proxy support via reqwest | — |
graph |
Integration with stygian-graph HTTP adapters | — |
browser |
Integration with stygian-browser pool (ProxyManagerBridge + ProxyLeaseAdapter) |
— |
tls-profiled |
TLS fingerprint profiling for proxy connections (requires browser feature) |
— |
mcp |
MCP (Model Context Protocol) tools | — |
Features (Core Capabilities)
Installation
[]
= "*"
= { = "1", = ["full"] }
Enable optional features:
# SOCKS4/5 proxy support
= { = "*", = ["socks"] }
# Integration with stygian-graph HTTP adapters
= { = "*", = ["graph"] }
# Integration with stygian-browser pool
= { = "*", = ["browser"] }
Quick Start
use ;
use Arc;
use Duration;
async
Rotation Strategies
| Strategy | Constructor | Behaviour |
|---|---|---|
RoundRobinStrategy |
ProxyManager::with_round_robin |
Cycles through healthy proxies in order |
RandomStrategy |
ProxyManager::with_random |
Picks a healthy proxy at random each time |
WeightedStrategy |
ProxyManager::with_weighted |
Selects proportionally to each proxy's weight field |
LeastUsedStrategy |
ProxyManager::with_least_used |
Prefers the proxy with the lowest total request count |
Custom strategies implement RotationStrategy:
use ;
use ProxyResult;
use async_trait;
;
IP Class and Target-Vendor Compatibility
Per the 2026 scraping guide, anti-bot vendors rank proxy egress IPs into a
four-tier trust hierarchy. stygian-proxy exposes this directly so
acquisition can route "scrape Akamai" → ISP-static, "scrape DataDome" →
mobile, and "scrape public data" → free-list datacenter.
use ;
// Filter acquisitions to mobile-class proxies only.
let req = CapabilityRequirement ;
// Acquire a proxy that meets the requirement.
# async
Every free-list fetcher (FreeListFetcher, FreeApiProxiesFetcher,
DnsTxtFetcher) tags ingested proxies as IpClass::Datacenter and
TargetVendorCompatibility::default_blocked() so callers cannot
accidentally route premium traffic through a public free-list pool. To
opt a proxy back in, override the per-proxy fields at registration.
Circuit Breaker
Each proxy has its own CircuitBreaker. After circuit_open_threshold consecutive failures the breaker opens, and the proxy is excluded from rotation for circuit_half_open_after. After that window the proxy is tried once in HalfOpen state — a success closes it; another failure reopens it.
use ;
use Arc;
use Duration;
let config = ProxyConfig ;
let manager = with_round_robin?;
If a ProxyHandle is dropped without calling mark_success(), the circuit breaker records a failure automatically.
Health Checking
ProxyManager::start() spawns a background task that probes each proxy on a configurable interval and updates per-proxy health scores:
use ;
use Arc;
use Duration;
let config = ProxyConfig ;
let manager = with_round_robin?;
let = manager.start;
// Graceful shutdown
cancel_token.cancel;
stygian-graph Integration
With the graph feature, the pool implements ProxyManagerPort so stygian-graph adapters can rotate proxies per-request:
= { = "*", = ["graph"] }
= "*"
use ;
use ProxyConfig;
use Arc;
let manager = with_round_robin?;
// Pass as Arc<dyn ProxyManagerPort> to RestApiAdapter or HttpAdapter
stygian-browser Integration
With the browser feature, ProxyManagerBridge implements [stygian_browser::proxy::ProxySource] so
stygian-browser contexts can acquire live pool proxies at launch time:
= { = "*", = ["browser"] }
= "*"
use ;
use ProxyConfig;
use BrowserConfig;
use Arc;
let manager = new;
let bridge = new;
// Pass the bridge to browser config
let config = builder
.proxy_source
.build;
// Each browser context acquires its own proxy from the pool
// On release: proxy success/failure automatically recorded to circuit breaker
Under the hood:
ProxyManagerBridgeimplementsProxySource(browser's port trait)- Each acquired proxy is wrapped in
ProxyLeaseAdapter - When
mark_success()is called on the lease, it updates the proxy's circuit breaker - On drop without marked success, the proxy is recorded as failed
License
AGPL-3.0-only OR LicenseRef-Commercial — see LICENSE and LICENSE-COMMERCIAL.md.