Metadata-Version: 2.4
Name: proxy-lane-checker
Version: 0.2.0
Summary: Dead proxies waste accounts — batch-check TCP, HTTP, geo, and DNSBL before assigning lanes.
Project-URL: Homepage, https://github.com/proxy-lane-checker/proxy-lane-checker
Project-URL: Documentation, https://github.com/proxy-lane-checker/proxy-lane-checker#readme
Project-URL: Repository, https://github.com/proxy-lane-checker/proxy-lane-checker
Project-URL: Issues, https://github.com/proxy-lane-checker/proxy-lane-checker/issues
Author: proxy-lane-checker contributors
License-Expression: MIT
License-File: LICENSE
Keywords: datacenter-proxy,dnsbl-check,geoip-proxy,http-proxy,lane-checker,proxy-batch,proxy-checker,proxy-health,proxy-latency,proxy-validator,residential-proxy,socks5-proxy
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: click>=8.1
Requires-Dist: httpx[socks]>=0.27
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.0
Provides-Extra: dev
Requires-Dist: httpx[socks]>=0.27; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest-httpx>=0.34; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.8; extra == 'dev'
Provides-Extra: mlx
Requires-Dist: httpx>=0.27; extra == 'mlx'
Description-Content-Type: text/markdown

# proxy-lane-checker

Python 3.10+ | MLX optional · [Compatibility](../packages/COMPATIBILITY.md)

Concurrent **proxy validator** — TCP connect, HTTP through proxy, optional geo IP lookup, latency p50/p95, and optional DNSBL listing.

Outputs JSON with pass/fail per proxy and recommended tags: `residential`, `datacenter`, `dead`.

## Problem

Proxy lists rot quickly. Before assigning IPs to scrapers or antidetect profiles, you need:

- Can we reach the host:port?
- Does HTTP actually work through the proxy?
- What country/ISP is the exit IP?
- Is latency acceptable (p50/p95)?
- Is the IP on a spam blacklist?

`proxy-lane` checks all of this concurrently and writes machine-readable results.

## pip install

```bash
pip install proxy-lane-checker
```

MLX profile proxy apply:

```bash
pip install proxy-lane-checker[mlx]
```

## Quick start

```bash
# Batch check a list (table to stdout, JSON saved to -o)
proxy-lane check proxies.txt --concurrency 20 --format table -o results.json

# CSV for spreadsheets
proxy-lane check proxies.txt --format csv -o results.json

# Single proxy with geo
proxy-lane check --proxy socks5://user:pass@host:port --geo

# Dedupe before checking
proxy-lane dedupe proxies.txt -o proxies-unique.txt

# Import vendor CSV (column mapping only — no API keys)
proxy-lane import examples/brightdata.sample.csv --format brightdata -o proxies.txt
proxy-lane check examples/oxylabs.sample.csv --import-format oxylabs --geo

# Pretty-print saved results
proxy-lane report results.json --format table
```

## Walkthrough: 48 proxies → 12 dead → tag residential

You bought a mixed list and need to know what is alive, what is dead, and which exits look residential before assigning them to MLX profiles.

```bash
# 1. Remove duplicate lines (vendor lists often repeat)
proxy-lane dedupe proxies.txt -o proxies-unique.txt
# Deduped 48 -> 45 (3 removed) -> proxies-unique.txt

# 2. Check with geo + limited concurrency (retries transient timeouts)
proxy-lane check proxies-unique.txt \
  --concurrency 10 \
  --geo \
  --format table \
  -o results.json
# Checked ... — total=45 passed=33 failed=12
# Table shows tags: dead, datacenter, residential, unknown

# 3. Export CSV for filtering in a spreadsheet
proxy-lane report results.json --format csv > results.csv
# Filter rows where tags contains "residential" and passed=yes

# 4. Apply a winner to an MLX profile
export MLX_TOKEN="..."
proxy-lane mlx-apply --profile-id "$PROFILE_ID" --proxy socks5://user:pass@residential-host:1080
```

In this example **48** lines became **45** unique after dedupe; **12** failed TCP/HTTP (`dead` tag); the remaining **33** get geo-based tags — pick `residential` for consumer ISP exits, `datacenter` for hosting ASNs.

## CLI

| Command | Description |
|---------|-------------|
| `proxy-lane check FILE` | Batch validate proxies from text file |
| `proxy-lane check --proxy URL` | Check one proxy |
| `proxy-lane check --format csv\|json\|table` | Stdout format (`-o` always JSON) |
| `proxy-lane check --concurrency N` | Asyncio semaphore limit (default 20) |
| `proxy-lane import FILE --format brightdata\|oxylabs\|generic` | Vendor CSV → `host:port[:user:pass]` lines |
| `proxy-lane check FILE --import-format FORMAT` | Check vendor CSV directly (YAML maps in `examples/`) |
| `proxy-lane dedupe FILE [-o OUT]` | Remove duplicate proxy lines |
| `proxy-lane report FILE --format csv\|json\|table` | Format saved JSON results |
| `proxy-lane mlx-apply --profile-id UUID --proxy URL` | Apply proxy to MLX profile (`[mlx]`) |

### Vendor CSV import

Maps common proxy list exports via YAML column configs in [`examples/`](examples/) — **no API keys**, only header → field mapping.

| `--format` | Mapping file | Typical columns |
|------------|--------------|-----------------|
| `brightdata` | `examples/brightdata.mapping.yaml` | `host`, `port`, `username`, `password` |
| `oxylabs` | `examples/oxylabs.mapping.yaml` | `ip`, `port`, `user`, `password` |
| `generic` | `examples/generic.mapping.yaml` | Edit `columns` to match your CSV |

```bash
# Convert CSV to proxies.txt
proxy-lane import vendor.csv --format oxylabs -o proxies.txt

# Custom mapping (copy generic.mapping.yaml)
proxy-lane import vendor.csv --format generic --mapping my.mapping.yaml -o proxies.txt

# Check without writing an intermediate file
proxy-lane check vendor.csv --import-format brightdata --concurrency 10 -o results.json
```

Sample fixtures: `examples/*.sample.csv` paired with `examples/*.mapping.yaml`.

### Proxy line formats

```
http://user:pass@host:8080
socks5://user:pass@host:1080
host:port
host:port:user:pass
```

Lines starting with `#` are ignored.

### Checks performed

| Check | Description |
|-------|-------------|
| TCP | `asyncio.open_connection` to proxy host:port |
| HTTP | GET via proxy (default `http://httpbin.org/ip`) |
| Geo | `ip-api.com` JSON through proxy (`--geo`) |
| Latency | Multiple HTTP samples → p50 / p95 ms |
| DNSBL | Optional Spamhaus-style lookup (`--dnsbl`) |
| Retry | Up to 2 retries on transient timeouts / 5xx only |

### Tags

| Tag | When |
|-----|------|
| `dead` | TCP or HTTP failed |
| `datacenter` | Hosting ASN/org keywords or `hosting=true` from geo API |
| `residential` | Mobile ISP signals or residential org keywords |
| `unknown` | Alive but inconclusive classification |

### Exit codes

| Code | Meaning |
|------|---------|
| `0` | All proxies passed |
| `1` | One or more proxies failed |
| `2` | Runtime error |

## API

```python
from proxy_lane_checker import ProxyChecker, ProxySpec
from proxy_lane_checker.runner import CheckOptions

checker = ProxyChecker(CheckOptions(concurrency=20, geo=True))
batch = checker.run([ProxySpec.from_url("socks5://user:pass@1.2.3.4:1080")])
for item in batch.results:
    print(item.proxy.display, item.passed, item.tags, item.latency_p95_ms)
```

## MLX apply (`[mlx]` extra)

Apply a **validated** proxy from check results or a direct URL. See [docs/MLX_INTEGRATION.md](docs/MLX_INTEGRATION.md) (pairs with **profile-yaml-factory**).

```bash
export MLX_TOKEN="your-bearer-token"
proxy-lane check proxies.txt --geo -o results.json
proxy-lane mlx-apply --profile-id PROFILE_UUID --results results.json --tag residential
proxy-lane mlx-apply --profile-id PROFILE_UUID --results results.json --dry-run
```

- Default: `PATCH /profile/partial_update` (proxy + `proxy_masking=custom`)
- `--full`: `POST /profile/update`
- `--dry-run`: print redacted payload, no API call

## Limitations

- **HTTP test URL** — default probe uses `httpbin.org`; blocked networks need a custom URL (future flag) or offline TCP-only inference.
- **Geo provider** — uses ip-api.com free tier (HTTP, rate limits); not a commercial geo database.
- **DNSBL accuracy** — public DNS resolvers may block or rate-limit DNSBL queries; treat as advisory.
- **Tag heuristics** — `residential` / `datacenter` are keyword + API flags, not ground truth.
- **SOCKS4** — parsed but prefer SOCKS5 for auth support.

## Production

Partner offers, eligibility, and disclosure: [docs/AFFILIATE.md](docs/AFFILIATE.md).

Typical workflow with antidetect profiles:

```bash
proxy-lane check proxies.txt --concurrency 20 --geo --dnsbl -o results.json
proxy-lane report results.json --format table
export MLX_TOKEN="..."
proxy-lane mlx-apply --profile-id "$PROFILE_ID" --results results.json --tag residential
```

Pair with [cookie-jar-bridge](https://github.com/cookie-jar-bridge/cookie-jar-bridge) and [playwright-cdp-probe](https://github.com/playwright-cdp-probe/playwright-cdp-probe) for full session QA.

## Guides

Monorepo playbooks (copy-paste commands, sample output, diagrams):

| Guide | Flow |
|-------|------|
| [Detection fail → MLX farm](../packages/docs/workflows/WORKFLOW_DETECTED.md) | `cdp-probe` → `cdp-connect` → `farm-runner mlx-pool` |
| [Competitor migration](../packages/docs/workflows/WORKFLOW_MIGRATION.md) | `antidetect-import` → `profile-factory mlx-create` |
| [Proxy lane → profile pool](../packages/docs/workflows/WORKFLOW_FARM.md) | `proxy-lane` → `profile-factory` → `farm-runner mlx-pool` |

**FAQ:** [docs/FAQ.md](docs/FAQ.md) — SOCKS5 checks, residential vs datacenter, DNSBL.

## Related tools

| Tool | Use with |
|------|----------|
| [playwright-cdp-probe](../playwright-cdp-probe/) — Score CDP/WebDriver exposure and fingerprint leaks | → [cdp-connect-kit](../cdp-connect-kit/) when probe fails |
| [cookie-jar-bridge](../cookie-jar-bridge/) — Convert, validate, and merge cookies across formats | → [session-bundle-kit](../session-bundle-kit/) for full session |
| [proxy-lane-checker](../proxy-lane-checker/) — Batch-check proxies for connectivity, geo, and DNSBL | → [profile-yaml-factory](../profile-yaml-factory/) |
| [fingerprint-coherence](../fingerprint-coherence/) — Lint fingerprints for cross-signal contradictions | → [profile-yaml-factory](../profile-yaml-factory/) before create |
| [human-input-kit](../human-input-kit/) — Human-like mouse, scroll, and warmup replay | → [automation-farm-runner](../automation-farm-runner/) |
| [cdp-connect-kit](../cdp-connect-kit/) — Playwright CDP connect; MLX start/stop helpers | → all packages needing CDP |
| [session-bundle-kit](../session-bundle-kit/) — Export/import cookies and storage as portable bundles | → [cookie-jar-bridge](../cookie-jar-bridge/) |
| [profile-yaml-factory](../profile-yaml-factory/) — YAML blueprints → MLX `profile/create` payloads | → [antidetect-importer](../antidetect-importer/) after migration |
| [antidetect-importer](../antidetect-importer/) — Parse competitor exports and push to MLX | → [profile-yaml-factory](../profile-yaml-factory/) |
| [automation-farm-runner](../automation-farm-runner/) — YAML job queue and MLX profile-pool runner | → [cdp-connect-kit](../cdp-connect-kit/) `[mlx]` |

## License

MIT

---

**Production antidetect:** [Multilogin X](https://multilogin.com/?ref=SAAS50) · Code `SAAS50` (-50% browser) · `MIN50` (-50% cloud phone)  
More scripts: [@Multilogin_Scripts_Bot](https://t.me/Multilogin_Scripts_Bot) · [Coupons](https://anti-detect.github.io/)
