proxy-scraper-cli 1.20.0__tar.gz → 1.22.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/PKG-INFO +66 -6
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/README.md +65 -5
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxy_scraper_cli.egg-info/PKG-INFO +66 -6
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxy_scraper_cli.egg-info/SOURCES.txt +4 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/__init__.py +1 -1
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/app.py +10 -3
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/cli.py +6 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/options.py +9 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/pipeline.py +22 -8
- proxy_scraper_cli-1.22.0/proxyscraper/preferences.py +59 -0
- proxy_scraper_cli-1.22.0/proxyscraper/server/api.py +186 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/server/core.py +28 -7
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/server/pool.py +9 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/site/index.html +46 -13
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/sources.py +24 -0
- proxy_scraper_cli-1.22.0/tests/test_own_sources.py +98 -0
- proxy_scraper_cli-1.22.0/tests/test_preferences.py +37 -0
- proxy_scraper_cli-1.22.0/tests/test_serve_api.py +153 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_server.py +2 -1
- proxy_scraper_cli-1.20.0/proxyscraper/preferences.py +0 -24
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/LICENSE +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxy_scraper_cli.egg-info/dependency_links.txt +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxy_scraper_cli.egg-info/entry_points.txt +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxy_scraper_cli.egg-info/requires.txt +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxy_scraper_cli.egg-info/top_level.txt +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/__main__.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/action.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/agent.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/api.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/asndb.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/blocklist.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/charts.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/checker.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/compat.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/completion.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/exporters.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/fetchcache.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/geo.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/geodb.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/handshake.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/history.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/judges.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/mcp_entry.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/mcp_server.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/netio.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/output.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/pages.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/parsing.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/paths.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/proxypages.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/publish.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/ranking.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/report.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/runsteps.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/server/__init__.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/server/http.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/server/socks.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/server/status.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/server/upstream.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/site/apple-touch-icon.png +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/site/googleaac1161b7853c5b5.html +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/site/logo.png +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/site/og.png +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/sites.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/sources.json +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/speed.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/targets.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/ui/__init__.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/ui/dashboard.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/ui/keys.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/ui/report.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/ui/serve.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/ui/widgets.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxyscraper/ui/wizard.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/pyproject.toml +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/setup.cfg +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_action.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_agent.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_api.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_app.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_asndb.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_auth.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_blocklist.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_charts.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_checker.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_compat.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_completion.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_discovery_growth.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_exporters.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_fetchcache.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_geodb.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_judges.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_learning.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_live_api.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_mcp_server.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_mine_sources.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_options.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_output_stdout.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_packaging.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_pages.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_parsing.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_parsing_fuzz.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_paths.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_pick.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_pipeline.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_proxy_pages.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_proxy_sources.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_publish.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_report.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_robustness.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_rotator.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_serve_password.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_serve_refill.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_serve_v2.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_server_closed_writer.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_server_fixes.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_sites.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_sources_json.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_speed.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_speed_ranking.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_tamper.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_targets.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_ui.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_uptime.py +0 -0
- {proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/tests/test_wizard.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: proxy-scraper-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.22.0
|
|
4
4
|
Summary: Finds free HTTP, SOCKS4 and SOCKS5 proxies that actually work: 700+ sources, real checks, honeypot filtering and a rotating local proxy server.
|
|
5
5
|
Author: Maximilian Feix
|
|
6
6
|
License-Expression: MIT
|
|
@@ -52,6 +52,7 @@ Dynamic: license-file
|
|
|
52
52
|
[](#live-list)
|
|
53
53
|
[](https://pypi.org/project/proxy-scraper-cli/)
|
|
54
54
|
[](pyproject.toml)
|
|
55
|
+
[](https://github.com/maximilianfeix/proxy-scraper/stargazers)
|
|
55
56
|
[](LICENSE)
|
|
56
57
|
|
|
57
58
|
<a href="https://maximilianfeix.github.io/proxy-scraper/"><img src="https://img.shields.io/badge/Browse_the_live_list-D4F77A?style=for-the-badge&labelColor=121113" alt="Browse the live list"></a>
|
|
@@ -68,6 +69,8 @@ Dynamic: license-file
|
|
|
68
69
|
|
|
69
70
|
Most free proxy lists are 95 % dead, and a good part of the rest are honeypots or proxies that inject scripts into your pages. **proxy-scraper** collects public HTTP, SOCKS4 and SOCKS5 proxies from 700+ sources and keeps only the ones that pass every check. It learns with every run which sources are worth it, and it can turn the result into a single rotating proxy.
|
|
70
71
|
|
|
72
|
+
**In numbers:** in one day it checked 3.6 million free proxies – 1.1 % worked, and more than half of the ones that answered failed a second request. [What's actually out there →](docs/free-proxies-in-numbers.md)
|
|
73
|
+
|
|
71
74
|
<picture>
|
|
72
75
|
<source media="(prefers-color-scheme: dark)" srcset="docs/checks-dark.svg">
|
|
73
76
|
<source media="(prefers-color-scheme: light)" srcset="docs/checks-light.svg">
|
|
@@ -94,7 +97,7 @@ Most free proxy lists are 95 % dead, and a good part of the rest are honeypots o
|
|
|
94
97
|
- [Options](#options)
|
|
95
98
|
- [GitHub Actions](#github-actions)
|
|
96
99
|
- [FAQ](#faq)
|
|
97
|
-
- [Roadmap](#roadmap) · [Contributing](#contributing) · [Acknowledgements](#acknowledgements)
|
|
100
|
+
- [Roadmap](#roadmap) · [Contributing](#contributing) · [Community](#community) · [Acknowledgements](#acknowledgements)
|
|
98
101
|
|
|
99
102
|
</details>
|
|
100
103
|
|
|
@@ -147,7 +150,7 @@ proxy-scraper --completion fish > ~/.config/fish/completions/proxy-scraper.fish
|
|
|
147
150
|
proxy-scraper --completion powershell | Out-String | Invoke-Expression # in $PROFILE
|
|
148
151
|
```
|
|
149
152
|
|
|
150
|
-
Installed, the learned state lives in your user data folder (`~/Library/Application Support/proxy-scraper`, `%LOCALAPPDATA%\proxy-scraper` or `~/.local/share/proxy-scraper`; override with `PROXY_SCRAPER_HOME`) and results go to `./results`. Run from a clone, both stay inside the project.
|
|
153
|
+
Installed, the learned state lives in your user data folder (`~/Library/Application Support/proxy-scraper`, `%LOCALAPPDATA%\proxy-scraper` or `~/.local/share/proxy-scraper`; override with `PROXY_SCRAPER_HOME`) and results go to `./results`. Run from a clone, both stay inside the project. After the second run that finds proxies it asks once for a GitHub star; `PROXY_SCRAPER_NO_STAR_HINT=1` turns that off (it never shows in CI).
|
|
151
154
|
|
|
152
155
|
</details>
|
|
153
156
|
|
|
@@ -384,6 +387,7 @@ macOS, Linux and Windows, Python 3.9 to 3.13. Only two dependencies: `rich` and
|
|
|
384
387
|
| Only proxies that reach *your* target site | ❌ | ✅ `--target` |
|
|
385
388
|
| Learns which sources are worth it | ❌ | ✅ |
|
|
386
389
|
| Usable as a single rotating proxy | ❌ | ✅ `--serve` |
|
|
390
|
+
| API to fetch a proxy (proxy_pool compatible) | ❌ | ✅ [`/get`](#pool-api) |
|
|
387
391
|
| Ready-made list without running anything | ✅ | ✅ [live list](#live-list) |
|
|
388
392
|
|
|
389
393
|
<a id="examples"></a>
|
|
@@ -519,6 +523,38 @@ Without a password, `--serve-host` means **anyone who reaches the port can use i
|
|
|
519
523
|
|
|
520
524
|
In testing: 20 of 20 HTTPS requests succeeded, over 15 different exit IPs. In the wizard this is **Proxy server right away**.
|
|
521
525
|
|
|
526
|
+
<a id="pool-api"></a>
|
|
527
|
+
|
|
528
|
+
### Proxy pool API
|
|
529
|
+
|
|
530
|
+
Some programs want a proxy *address*, not a proxy – to hand it to a browser, a worker or a queue. The same port answers plain HTTP requests with one:
|
|
531
|
+
|
|
532
|
+
```bash
|
|
533
|
+
curl http://127.0.0.1:8899/get # one proxy as JSON, chosen like a connection would be
|
|
534
|
+
curl "http://127.0.0.1:8899/get?country=DE&https=1&format=txt" # → http://203.0.113.7:8080
|
|
535
|
+
curl "http://127.0.0.1:8899/all?protocol=socks5&limit=20" # the 20 best SOCKS5 proxies
|
|
536
|
+
curl "http://127.0.0.1:8899/report?proxy=203.0.113.7:8080&ok=0" # it failed you – three times and it's out
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
| Endpoint | What it does |
|
|
540
|
+
|---|---|
|
|
541
|
+
| `/get` | one proxy, picked by the `--rotate` strategy |
|
|
542
|
+
| `/pop` | like `/get`, and the proxy leaves the pool |
|
|
543
|
+
| `/all` | every usable proxy, best first (`limit=N`) |
|
|
544
|
+
| `/count` | totals by type and country |
|
|
545
|
+
| `/delete?proxy=IP:PORT` | take a proxy out |
|
|
546
|
+
| `/report?proxy=IP:PORT&ok=0` | feedback from your own requests |
|
|
547
|
+
|
|
548
|
+
Filters work on `/get`, `/pop` and `/all`: `country=DE,AT`, `protocol=socks5`, `https=1`, `anonymity=elite`, `max_latency=1500`, and `format=txt` for plain URLs. With `--serve-password` the API wants it as Basic auth, like the status page.
|
|
549
|
+
|
|
550
|
+
**Coming from [jhao104/proxy_pool](https://github.com/jhao104/proxy_pool)?** The endpoints, `type=https` and the JSON fields (`proxy`, `https`, `region`, `anonymous`, `check_count`, `fail_count`, …) are the same, so point your code at port 8899 and it keeps working – without Redis, and with proxies that passed the honeypot, tampering and TLS checks:
|
|
551
|
+
|
|
552
|
+
```python
|
|
553
|
+
import requests
|
|
554
|
+
proxy = requests.get("http://127.0.0.1:8899/get?type=https").json()["url"] # e.g. socks5://…, type included
|
|
555
|
+
requests.get("https://example.com", proxies={"http": proxy, "https": proxy})
|
|
556
|
+
```
|
|
557
|
+
|
|
522
558
|
<a id="discord-bot"></a>
|
|
523
559
|
|
|
524
560
|
## Discord and Telegram bot
|
|
@@ -558,6 +594,15 @@ flowchart LR
|
|
|
558
594
|
</div>
|
|
559
595
|
</details>
|
|
560
596
|
|
|
597
|
+
### Your own lists
|
|
598
|
+
|
|
599
|
+
```bash
|
|
600
|
+
proxy-scraper --source https://example.com/my-list.txt --source socks5=./socks.txt # on top of the 700+ sources
|
|
601
|
+
proxy-scraper --only-sources --source bought.txt --want 50 # only yours
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
Any text with `ip:port` works; lines like `socks5://user:pass@host:port` keep their type, bare ones are tried as HTTP and SOCKS5 unless you write `http=…`.
|
|
605
|
+
|
|
561
606
|
<a id="output"></a>
|
|
562
607
|
|
|
563
608
|
## Output
|
|
@@ -875,8 +920,9 @@ Only for things that don't matter. Public proxies are run by strangers who can r
|
|
|
875
920
|
|
|
876
921
|
What's next is in the [open issues](../../issues) – ideas and wishes are welcome as an [issue](../../issues/new/choose). During Hacktoberfest there are [beginner-friendly issues](../../issues?q=is%3Aopen+label%3Ahacktoberfest) with pointers on where to start.
|
|
877
922
|
|
|
878
|
-
- [ ] [
|
|
879
|
-
|
|
923
|
+
- [ ] [Mirror the daily snapshots to a Hugging Face dataset](../../issues/188)
|
|
924
|
+
|
|
925
|
+
Shipped in v1.10 to v1.21: download speed per proxy and "best first" everywhere, daily snapshots, a rotating proxy URL for requests, httpx and Playwright, `--pick` for working proxies without a scan, a proxy pool API compatible with jhao104/proxy_pool, your own lists with `--source`, a GitHub Action, a Telegram bot and an Atom feed for the weekly report.
|
|
880
926
|
|
|
881
927
|
Shipped in v1.8 and v1.9: uptime per proxy and `stable.txt`, which proxies get through to Google, Reddit and Amazon, `live_proxies()` in Python, a page per proxy with its week of checks, a weekly report, live charts in this README, shareable filters on the website, sources mined from other scrapers' lists, untyped lists tried as HTTP and SOCKS5, `--export singbox`, PowerShell completion and recipes for httpx, aiohttp and Scrapy.
|
|
882
928
|
|
|
@@ -924,7 +970,7 @@ proxyscraper/
|
|
|
924
970
|
├── targets.py target sites for --target
|
|
925
971
|
├── output.py result files
|
|
926
972
|
├── exporters.py proxychains, Clash, sing-box and curl formats (--export)
|
|
927
|
-
├── server/ rotating proxy server (--serve): pool · http · upstream · socks · status · core
|
|
973
|
+
├── server/ rotating proxy server (--serve): pool · http · upstream · socks · status · api · core
|
|
928
974
|
├── api.py find_proxies() / check_proxies() for Python
|
|
929
975
|
├── agent.py MCP tools without the SDK: live list, filters, fetch through proxies
|
|
930
976
|
├── mcp_server.py MCP server (proxy-scraper-mcp) for AI agents
|
|
@@ -937,6 +983,20 @@ proxyscraper/
|
|
|
937
983
|
|
|
938
984
|
</details>
|
|
939
985
|
|
|
986
|
+
<a id="community"></a>
|
|
987
|
+
|
|
988
|
+
## Community
|
|
989
|
+
|
|
990
|
+
Questions, ideas and things you built with it go to [Discussions](https://github.com/maximilianfeix/proxy-scraper/discussions) – bugs to the [issues](../../issues). If proxy-scraper saves you time, a ⭐ helps others find it.
|
|
991
|
+
|
|
992
|
+
<a href="https://star-history.com/#maximilianfeix/proxy-scraper&Date">
|
|
993
|
+
<picture>
|
|
994
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=maximilianfeix/proxy-scraper&type=Date&theme=dark">
|
|
995
|
+
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=maximilianfeix/proxy-scraper&type=Date">
|
|
996
|
+
<img alt="Star history of proxy-scraper" src="https://api.star-history.com/svg?repos=maximilianfeix/proxy-scraper&type=Date" width="600">
|
|
997
|
+
</picture>
|
|
998
|
+
</a>
|
|
999
|
+
|
|
940
1000
|
<a id="acknowledgements"></a>
|
|
941
1001
|
|
|
942
1002
|
## Acknowledgements
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
[](#live-list)
|
|
12
12
|
[](https://pypi.org/project/proxy-scraper-cli/)
|
|
13
13
|
[](pyproject.toml)
|
|
14
|
+
[](https://github.com/maximilianfeix/proxy-scraper/stargazers)
|
|
14
15
|
[](LICENSE)
|
|
15
16
|
|
|
16
17
|
<a href="https://maximilianfeix.github.io/proxy-scraper/"><img src="https://img.shields.io/badge/Browse_the_live_list-D4F77A?style=for-the-badge&labelColor=121113" alt="Browse the live list"></a>
|
|
@@ -27,6 +28,8 @@
|
|
|
27
28
|
|
|
28
29
|
Most free proxy lists are 95 % dead, and a good part of the rest are honeypots or proxies that inject scripts into your pages. **proxy-scraper** collects public HTTP, SOCKS4 and SOCKS5 proxies from 700+ sources and keeps only the ones that pass every check. It learns with every run which sources are worth it, and it can turn the result into a single rotating proxy.
|
|
29
30
|
|
|
31
|
+
**In numbers:** in one day it checked 3.6 million free proxies – 1.1 % worked, and more than half of the ones that answered failed a second request. [What's actually out there →](docs/free-proxies-in-numbers.md)
|
|
32
|
+
|
|
30
33
|
<picture>
|
|
31
34
|
<source media="(prefers-color-scheme: dark)" srcset="docs/checks-dark.svg">
|
|
32
35
|
<source media="(prefers-color-scheme: light)" srcset="docs/checks-light.svg">
|
|
@@ -53,7 +56,7 @@ Most free proxy lists are 95 % dead, and a good part of the rest are honeypots o
|
|
|
53
56
|
- [Options](#options)
|
|
54
57
|
- [GitHub Actions](#github-actions)
|
|
55
58
|
- [FAQ](#faq)
|
|
56
|
-
- [Roadmap](#roadmap) · [Contributing](#contributing) · [Acknowledgements](#acknowledgements)
|
|
59
|
+
- [Roadmap](#roadmap) · [Contributing](#contributing) · [Community](#community) · [Acknowledgements](#acknowledgements)
|
|
57
60
|
|
|
58
61
|
</details>
|
|
59
62
|
|
|
@@ -106,7 +109,7 @@ proxy-scraper --completion fish > ~/.config/fish/completions/proxy-scraper.fish
|
|
|
106
109
|
proxy-scraper --completion powershell | Out-String | Invoke-Expression # in $PROFILE
|
|
107
110
|
```
|
|
108
111
|
|
|
109
|
-
Installed, the learned state lives in your user data folder (`~/Library/Application Support/proxy-scraper`, `%LOCALAPPDATA%\proxy-scraper` or `~/.local/share/proxy-scraper`; override with `PROXY_SCRAPER_HOME`) and results go to `./results`. Run from a clone, both stay inside the project.
|
|
112
|
+
Installed, the learned state lives in your user data folder (`~/Library/Application Support/proxy-scraper`, `%LOCALAPPDATA%\proxy-scraper` or `~/.local/share/proxy-scraper`; override with `PROXY_SCRAPER_HOME`) and results go to `./results`. Run from a clone, both stay inside the project. After the second run that finds proxies it asks once for a GitHub star; `PROXY_SCRAPER_NO_STAR_HINT=1` turns that off (it never shows in CI).
|
|
110
113
|
|
|
111
114
|
</details>
|
|
112
115
|
|
|
@@ -343,6 +346,7 @@ macOS, Linux and Windows, Python 3.9 to 3.13. Only two dependencies: `rich` and
|
|
|
343
346
|
| Only proxies that reach *your* target site | ❌ | ✅ `--target` |
|
|
344
347
|
| Learns which sources are worth it | ❌ | ✅ |
|
|
345
348
|
| Usable as a single rotating proxy | ❌ | ✅ `--serve` |
|
|
349
|
+
| API to fetch a proxy (proxy_pool compatible) | ❌ | ✅ [`/get`](#pool-api) |
|
|
346
350
|
| Ready-made list without running anything | ✅ | ✅ [live list](#live-list) |
|
|
347
351
|
|
|
348
352
|
<a id="examples"></a>
|
|
@@ -478,6 +482,38 @@ Without a password, `--serve-host` means **anyone who reaches the port can use i
|
|
|
478
482
|
|
|
479
483
|
In testing: 20 of 20 HTTPS requests succeeded, over 15 different exit IPs. In the wizard this is **Proxy server right away**.
|
|
480
484
|
|
|
485
|
+
<a id="pool-api"></a>
|
|
486
|
+
|
|
487
|
+
### Proxy pool API
|
|
488
|
+
|
|
489
|
+
Some programs want a proxy *address*, not a proxy – to hand it to a browser, a worker or a queue. The same port answers plain HTTP requests with one:
|
|
490
|
+
|
|
491
|
+
```bash
|
|
492
|
+
curl http://127.0.0.1:8899/get # one proxy as JSON, chosen like a connection would be
|
|
493
|
+
curl "http://127.0.0.1:8899/get?country=DE&https=1&format=txt" # → http://203.0.113.7:8080
|
|
494
|
+
curl "http://127.0.0.1:8899/all?protocol=socks5&limit=20" # the 20 best SOCKS5 proxies
|
|
495
|
+
curl "http://127.0.0.1:8899/report?proxy=203.0.113.7:8080&ok=0" # it failed you – three times and it's out
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
| Endpoint | What it does |
|
|
499
|
+
|---|---|
|
|
500
|
+
| `/get` | one proxy, picked by the `--rotate` strategy |
|
|
501
|
+
| `/pop` | like `/get`, and the proxy leaves the pool |
|
|
502
|
+
| `/all` | every usable proxy, best first (`limit=N`) |
|
|
503
|
+
| `/count` | totals by type and country |
|
|
504
|
+
| `/delete?proxy=IP:PORT` | take a proxy out |
|
|
505
|
+
| `/report?proxy=IP:PORT&ok=0` | feedback from your own requests |
|
|
506
|
+
|
|
507
|
+
Filters work on `/get`, `/pop` and `/all`: `country=DE,AT`, `protocol=socks5`, `https=1`, `anonymity=elite`, `max_latency=1500`, and `format=txt` for plain URLs. With `--serve-password` the API wants it as Basic auth, like the status page.
|
|
508
|
+
|
|
509
|
+
**Coming from [jhao104/proxy_pool](https://github.com/jhao104/proxy_pool)?** The endpoints, `type=https` and the JSON fields (`proxy`, `https`, `region`, `anonymous`, `check_count`, `fail_count`, …) are the same, so point your code at port 8899 and it keeps working – without Redis, and with proxies that passed the honeypot, tampering and TLS checks:
|
|
510
|
+
|
|
511
|
+
```python
|
|
512
|
+
import requests
|
|
513
|
+
proxy = requests.get("http://127.0.0.1:8899/get?type=https").json()["url"] # e.g. socks5://…, type included
|
|
514
|
+
requests.get("https://example.com", proxies={"http": proxy, "https": proxy})
|
|
515
|
+
```
|
|
516
|
+
|
|
481
517
|
<a id="discord-bot"></a>
|
|
482
518
|
|
|
483
519
|
## Discord and Telegram bot
|
|
@@ -517,6 +553,15 @@ flowchart LR
|
|
|
517
553
|
</div>
|
|
518
554
|
</details>
|
|
519
555
|
|
|
556
|
+
### Your own lists
|
|
557
|
+
|
|
558
|
+
```bash
|
|
559
|
+
proxy-scraper --source https://example.com/my-list.txt --source socks5=./socks.txt # on top of the 700+ sources
|
|
560
|
+
proxy-scraper --only-sources --source bought.txt --want 50 # only yours
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
Any text with `ip:port` works; lines like `socks5://user:pass@host:port` keep their type, bare ones are tried as HTTP and SOCKS5 unless you write `http=…`.
|
|
564
|
+
|
|
520
565
|
<a id="output"></a>
|
|
521
566
|
|
|
522
567
|
## Output
|
|
@@ -834,8 +879,9 @@ Only for things that don't matter. Public proxies are run by strangers who can r
|
|
|
834
879
|
|
|
835
880
|
What's next is in the [open issues](../../issues) – ideas and wishes are welcome as an [issue](../../issues/new/choose). During Hacktoberfest there are [beginner-friendly issues](../../issues?q=is%3Aopen+label%3Ahacktoberfest) with pointers on where to start.
|
|
836
881
|
|
|
837
|
-
- [ ] [
|
|
838
|
-
|
|
882
|
+
- [ ] [Mirror the daily snapshots to a Hugging Face dataset](../../issues/188)
|
|
883
|
+
|
|
884
|
+
Shipped in v1.10 to v1.21: download speed per proxy and "best first" everywhere, daily snapshots, a rotating proxy URL for requests, httpx and Playwright, `--pick` for working proxies without a scan, a proxy pool API compatible with jhao104/proxy_pool, your own lists with `--source`, a GitHub Action, a Telegram bot and an Atom feed for the weekly report.
|
|
839
885
|
|
|
840
886
|
Shipped in v1.8 and v1.9: uptime per proxy and `stable.txt`, which proxies get through to Google, Reddit and Amazon, `live_proxies()` in Python, a page per proxy with its week of checks, a weekly report, live charts in this README, shareable filters on the website, sources mined from other scrapers' lists, untyped lists tried as HTTP and SOCKS5, `--export singbox`, PowerShell completion and recipes for httpx, aiohttp and Scrapy.
|
|
841
887
|
|
|
@@ -883,7 +929,7 @@ proxyscraper/
|
|
|
883
929
|
├── targets.py target sites for --target
|
|
884
930
|
├── output.py result files
|
|
885
931
|
├── exporters.py proxychains, Clash, sing-box and curl formats (--export)
|
|
886
|
-
├── server/ rotating proxy server (--serve): pool · http · upstream · socks · status · core
|
|
932
|
+
├── server/ rotating proxy server (--serve): pool · http · upstream · socks · status · api · core
|
|
887
933
|
├── api.py find_proxies() / check_proxies() for Python
|
|
888
934
|
├── agent.py MCP tools without the SDK: live list, filters, fetch through proxies
|
|
889
935
|
├── mcp_server.py MCP server (proxy-scraper-mcp) for AI agents
|
|
@@ -896,6 +942,20 @@ proxyscraper/
|
|
|
896
942
|
|
|
897
943
|
</details>
|
|
898
944
|
|
|
945
|
+
<a id="community"></a>
|
|
946
|
+
|
|
947
|
+
## Community
|
|
948
|
+
|
|
949
|
+
Questions, ideas and things you built with it go to [Discussions](https://github.com/maximilianfeix/proxy-scraper/discussions) – bugs to the [issues](../../issues). If proxy-scraper saves you time, a ⭐ helps others find it.
|
|
950
|
+
|
|
951
|
+
<a href="https://star-history.com/#maximilianfeix/proxy-scraper&Date">
|
|
952
|
+
<picture>
|
|
953
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=maximilianfeix/proxy-scraper&type=Date&theme=dark">
|
|
954
|
+
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=maximilianfeix/proxy-scraper&type=Date">
|
|
955
|
+
<img alt="Star history of proxy-scraper" src="https://api.star-history.com/svg?repos=maximilianfeix/proxy-scraper&type=Date" width="600">
|
|
956
|
+
</picture>
|
|
957
|
+
</a>
|
|
958
|
+
|
|
899
959
|
<a id="acknowledgements"></a>
|
|
900
960
|
|
|
901
961
|
## Acknowledgements
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: proxy-scraper-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.22.0
|
|
4
4
|
Summary: Finds free HTTP, SOCKS4 and SOCKS5 proxies that actually work: 700+ sources, real checks, honeypot filtering and a rotating local proxy server.
|
|
5
5
|
Author: Maximilian Feix
|
|
6
6
|
License-Expression: MIT
|
|
@@ -52,6 +52,7 @@ Dynamic: license-file
|
|
|
52
52
|
[](#live-list)
|
|
53
53
|
[](https://pypi.org/project/proxy-scraper-cli/)
|
|
54
54
|
[](pyproject.toml)
|
|
55
|
+
[](https://github.com/maximilianfeix/proxy-scraper/stargazers)
|
|
55
56
|
[](LICENSE)
|
|
56
57
|
|
|
57
58
|
<a href="https://maximilianfeix.github.io/proxy-scraper/"><img src="https://img.shields.io/badge/Browse_the_live_list-D4F77A?style=for-the-badge&labelColor=121113" alt="Browse the live list"></a>
|
|
@@ -68,6 +69,8 @@ Dynamic: license-file
|
|
|
68
69
|
|
|
69
70
|
Most free proxy lists are 95 % dead, and a good part of the rest are honeypots or proxies that inject scripts into your pages. **proxy-scraper** collects public HTTP, SOCKS4 and SOCKS5 proxies from 700+ sources and keeps only the ones that pass every check. It learns with every run which sources are worth it, and it can turn the result into a single rotating proxy.
|
|
70
71
|
|
|
72
|
+
**In numbers:** in one day it checked 3.6 million free proxies – 1.1 % worked, and more than half of the ones that answered failed a second request. [What's actually out there →](docs/free-proxies-in-numbers.md)
|
|
73
|
+
|
|
71
74
|
<picture>
|
|
72
75
|
<source media="(prefers-color-scheme: dark)" srcset="docs/checks-dark.svg">
|
|
73
76
|
<source media="(prefers-color-scheme: light)" srcset="docs/checks-light.svg">
|
|
@@ -94,7 +97,7 @@ Most free proxy lists are 95 % dead, and a good part of the rest are honeypots o
|
|
|
94
97
|
- [Options](#options)
|
|
95
98
|
- [GitHub Actions](#github-actions)
|
|
96
99
|
- [FAQ](#faq)
|
|
97
|
-
- [Roadmap](#roadmap) · [Contributing](#contributing) · [Acknowledgements](#acknowledgements)
|
|
100
|
+
- [Roadmap](#roadmap) · [Contributing](#contributing) · [Community](#community) · [Acknowledgements](#acknowledgements)
|
|
98
101
|
|
|
99
102
|
</details>
|
|
100
103
|
|
|
@@ -147,7 +150,7 @@ proxy-scraper --completion fish > ~/.config/fish/completions/proxy-scraper.fish
|
|
|
147
150
|
proxy-scraper --completion powershell | Out-String | Invoke-Expression # in $PROFILE
|
|
148
151
|
```
|
|
149
152
|
|
|
150
|
-
Installed, the learned state lives in your user data folder (`~/Library/Application Support/proxy-scraper`, `%LOCALAPPDATA%\proxy-scraper` or `~/.local/share/proxy-scraper`; override with `PROXY_SCRAPER_HOME`) and results go to `./results`. Run from a clone, both stay inside the project.
|
|
153
|
+
Installed, the learned state lives in your user data folder (`~/Library/Application Support/proxy-scraper`, `%LOCALAPPDATA%\proxy-scraper` or `~/.local/share/proxy-scraper`; override with `PROXY_SCRAPER_HOME`) and results go to `./results`. Run from a clone, both stay inside the project. After the second run that finds proxies it asks once for a GitHub star; `PROXY_SCRAPER_NO_STAR_HINT=1` turns that off (it never shows in CI).
|
|
151
154
|
|
|
152
155
|
</details>
|
|
153
156
|
|
|
@@ -384,6 +387,7 @@ macOS, Linux and Windows, Python 3.9 to 3.13. Only two dependencies: `rich` and
|
|
|
384
387
|
| Only proxies that reach *your* target site | ❌ | ✅ `--target` |
|
|
385
388
|
| Learns which sources are worth it | ❌ | ✅ |
|
|
386
389
|
| Usable as a single rotating proxy | ❌ | ✅ `--serve` |
|
|
390
|
+
| API to fetch a proxy (proxy_pool compatible) | ❌ | ✅ [`/get`](#pool-api) |
|
|
387
391
|
| Ready-made list without running anything | ✅ | ✅ [live list](#live-list) |
|
|
388
392
|
|
|
389
393
|
<a id="examples"></a>
|
|
@@ -519,6 +523,38 @@ Without a password, `--serve-host` means **anyone who reaches the port can use i
|
|
|
519
523
|
|
|
520
524
|
In testing: 20 of 20 HTTPS requests succeeded, over 15 different exit IPs. In the wizard this is **Proxy server right away**.
|
|
521
525
|
|
|
526
|
+
<a id="pool-api"></a>
|
|
527
|
+
|
|
528
|
+
### Proxy pool API
|
|
529
|
+
|
|
530
|
+
Some programs want a proxy *address*, not a proxy – to hand it to a browser, a worker or a queue. The same port answers plain HTTP requests with one:
|
|
531
|
+
|
|
532
|
+
```bash
|
|
533
|
+
curl http://127.0.0.1:8899/get # one proxy as JSON, chosen like a connection would be
|
|
534
|
+
curl "http://127.0.0.1:8899/get?country=DE&https=1&format=txt" # → http://203.0.113.7:8080
|
|
535
|
+
curl "http://127.0.0.1:8899/all?protocol=socks5&limit=20" # the 20 best SOCKS5 proxies
|
|
536
|
+
curl "http://127.0.0.1:8899/report?proxy=203.0.113.7:8080&ok=0" # it failed you – three times and it's out
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
| Endpoint | What it does |
|
|
540
|
+
|---|---|
|
|
541
|
+
| `/get` | one proxy, picked by the `--rotate` strategy |
|
|
542
|
+
| `/pop` | like `/get`, and the proxy leaves the pool |
|
|
543
|
+
| `/all` | every usable proxy, best first (`limit=N`) |
|
|
544
|
+
| `/count` | totals by type and country |
|
|
545
|
+
| `/delete?proxy=IP:PORT` | take a proxy out |
|
|
546
|
+
| `/report?proxy=IP:PORT&ok=0` | feedback from your own requests |
|
|
547
|
+
|
|
548
|
+
Filters work on `/get`, `/pop` and `/all`: `country=DE,AT`, `protocol=socks5`, `https=1`, `anonymity=elite`, `max_latency=1500`, and `format=txt` for plain URLs. With `--serve-password` the API wants it as Basic auth, like the status page.
|
|
549
|
+
|
|
550
|
+
**Coming from [jhao104/proxy_pool](https://github.com/jhao104/proxy_pool)?** The endpoints, `type=https` and the JSON fields (`proxy`, `https`, `region`, `anonymous`, `check_count`, `fail_count`, …) are the same, so point your code at port 8899 and it keeps working – without Redis, and with proxies that passed the honeypot, tampering and TLS checks:
|
|
551
|
+
|
|
552
|
+
```python
|
|
553
|
+
import requests
|
|
554
|
+
proxy = requests.get("http://127.0.0.1:8899/get?type=https").json()["url"] # e.g. socks5://…, type included
|
|
555
|
+
requests.get("https://example.com", proxies={"http": proxy, "https": proxy})
|
|
556
|
+
```
|
|
557
|
+
|
|
522
558
|
<a id="discord-bot"></a>
|
|
523
559
|
|
|
524
560
|
## Discord and Telegram bot
|
|
@@ -558,6 +594,15 @@ flowchart LR
|
|
|
558
594
|
</div>
|
|
559
595
|
</details>
|
|
560
596
|
|
|
597
|
+
### Your own lists
|
|
598
|
+
|
|
599
|
+
```bash
|
|
600
|
+
proxy-scraper --source https://example.com/my-list.txt --source socks5=./socks.txt # on top of the 700+ sources
|
|
601
|
+
proxy-scraper --only-sources --source bought.txt --want 50 # only yours
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
Any text with `ip:port` works; lines like `socks5://user:pass@host:port` keep their type, bare ones are tried as HTTP and SOCKS5 unless you write `http=…`.
|
|
605
|
+
|
|
561
606
|
<a id="output"></a>
|
|
562
607
|
|
|
563
608
|
## Output
|
|
@@ -875,8 +920,9 @@ Only for things that don't matter. Public proxies are run by strangers who can r
|
|
|
875
920
|
|
|
876
921
|
What's next is in the [open issues](../../issues) – ideas and wishes are welcome as an [issue](../../issues/new/choose). During Hacktoberfest there are [beginner-friendly issues](../../issues?q=is%3Aopen+label%3Ahacktoberfest) with pointers on where to start.
|
|
877
922
|
|
|
878
|
-
- [ ] [
|
|
879
|
-
|
|
923
|
+
- [ ] [Mirror the daily snapshots to a Hugging Face dataset](../../issues/188)
|
|
924
|
+
|
|
925
|
+
Shipped in v1.10 to v1.21: download speed per proxy and "best first" everywhere, daily snapshots, a rotating proxy URL for requests, httpx and Playwright, `--pick` for working proxies without a scan, a proxy pool API compatible with jhao104/proxy_pool, your own lists with `--source`, a GitHub Action, a Telegram bot and an Atom feed for the weekly report.
|
|
880
926
|
|
|
881
927
|
Shipped in v1.8 and v1.9: uptime per proxy and `stable.txt`, which proxies get through to Google, Reddit and Amazon, `live_proxies()` in Python, a page per proxy with its week of checks, a weekly report, live charts in this README, shareable filters on the website, sources mined from other scrapers' lists, untyped lists tried as HTTP and SOCKS5, `--export singbox`, PowerShell completion and recipes for httpx, aiohttp and Scrapy.
|
|
882
928
|
|
|
@@ -924,7 +970,7 @@ proxyscraper/
|
|
|
924
970
|
├── targets.py target sites for --target
|
|
925
971
|
├── output.py result files
|
|
926
972
|
├── exporters.py proxychains, Clash, sing-box and curl formats (--export)
|
|
927
|
-
├── server/ rotating proxy server (--serve): pool · http · upstream · socks · status · core
|
|
973
|
+
├── server/ rotating proxy server (--serve): pool · http · upstream · socks · status · api · core
|
|
928
974
|
├── api.py find_proxies() / check_proxies() for Python
|
|
929
975
|
├── agent.py MCP tools without the SDK: live list, filters, fetch through proxies
|
|
930
976
|
├── mcp_server.py MCP server (proxy-scraper-mcp) for AI agents
|
|
@@ -937,6 +983,20 @@ proxyscraper/
|
|
|
937
983
|
|
|
938
984
|
</details>
|
|
939
985
|
|
|
986
|
+
<a id="community"></a>
|
|
987
|
+
|
|
988
|
+
## Community
|
|
989
|
+
|
|
990
|
+
Questions, ideas and things you built with it go to [Discussions](https://github.com/maximilianfeix/proxy-scraper/discussions) – bugs to the [issues](../../issues). If proxy-scraper saves you time, a ⭐ helps others find it.
|
|
991
|
+
|
|
992
|
+
<a href="https://star-history.com/#maximilianfeix/proxy-scraper&Date">
|
|
993
|
+
<picture>
|
|
994
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=maximilianfeix/proxy-scraper&type=Date&theme=dark">
|
|
995
|
+
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=maximilianfeix/proxy-scraper&type=Date">
|
|
996
|
+
<img alt="Star history of proxy-scraper" src="https://api.star-history.com/svg?repos=maximilianfeix/proxy-scraper&type=Date" width="600">
|
|
997
|
+
</picture>
|
|
998
|
+
</a>
|
|
999
|
+
|
|
940
1000
|
<a id="acknowledgements"></a>
|
|
941
1001
|
|
|
942
1002
|
## Acknowledgements
|
{proxy_scraper_cli-1.20.0 → proxy_scraper_cli-1.22.0}/proxy_scraper_cli.egg-info/SOURCES.txt
RENAMED
|
@@ -48,6 +48,7 @@ proxyscraper/sources.py
|
|
|
48
48
|
proxyscraper/speed.py
|
|
49
49
|
proxyscraper/targets.py
|
|
50
50
|
proxyscraper/server/__init__.py
|
|
51
|
+
proxyscraper/server/api.py
|
|
51
52
|
proxyscraper/server/core.py
|
|
52
53
|
proxyscraper/server/http.py
|
|
53
54
|
proxyscraper/server/pool.py
|
|
@@ -88,6 +89,7 @@ tests/test_mcp_server.py
|
|
|
88
89
|
tests/test_mine_sources.py
|
|
89
90
|
tests/test_options.py
|
|
90
91
|
tests/test_output_stdout.py
|
|
92
|
+
tests/test_own_sources.py
|
|
91
93
|
tests/test_packaging.py
|
|
92
94
|
tests/test_pages.py
|
|
93
95
|
tests/test_parsing.py
|
|
@@ -95,12 +97,14 @@ tests/test_parsing_fuzz.py
|
|
|
95
97
|
tests/test_paths.py
|
|
96
98
|
tests/test_pick.py
|
|
97
99
|
tests/test_pipeline.py
|
|
100
|
+
tests/test_preferences.py
|
|
98
101
|
tests/test_proxy_pages.py
|
|
99
102
|
tests/test_proxy_sources.py
|
|
100
103
|
tests/test_publish.py
|
|
101
104
|
tests/test_report.py
|
|
102
105
|
tests/test_robustness.py
|
|
103
106
|
tests/test_rotator.py
|
|
107
|
+
tests/test_serve_api.py
|
|
104
108
|
tests/test_serve_password.py
|
|
105
109
|
tests/test_serve_refill.py
|
|
106
110
|
tests/test_serve_v2.py
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""proxy-scraper: collects public HTTP/SOCKS4/SOCKS5 proxies from hundreds of sources, checks them
|
|
2
2
|
in parallel with its own protocol handshakes and learns which sources deliver good proxies."""
|
|
3
3
|
|
|
4
|
-
__version__ = "1.
|
|
4
|
+
__version__ = "1.22.0"
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def __getattr__(name):
|
|
@@ -41,6 +41,7 @@ from .judges import JudgeProbe, JudgeWatch, rank_judges
|
|
|
41
41
|
from .netio import INSECURE_HOSTS, http_get
|
|
42
42
|
from .options import STDOUT, RunOptions
|
|
43
43
|
from .output import ResultWriter, latest_results
|
|
44
|
+
from .pages import REPO_URL
|
|
44
45
|
from .parsing import PROXY_TYPES, parse_keys, split_key
|
|
45
46
|
from .paths import is_checkout
|
|
46
47
|
from .pipeline import (
|
|
@@ -53,6 +54,7 @@ from .pipeline import (
|
|
|
53
54
|
run_checks,
|
|
54
55
|
scrape,
|
|
55
56
|
)
|
|
57
|
+
from .preferences import star_hint_due
|
|
56
58
|
from .publish import RAW_BASE
|
|
57
59
|
from .server import ProxyPool, RotatingServer
|
|
58
60
|
from .targets import Target, parse_target
|
|
@@ -327,8 +329,10 @@ class Run:
|
|
|
327
329
|
plan = await collect_sources(self.opts, self.quality)
|
|
328
330
|
info("Sources", Text.assemble(
|
|
329
331
|
(fmt(len(plan.sources)), f"bold {ACCENT}"), " active ",
|
|
330
|
-
(f"({fmt(plan.
|
|
331
|
-
f"
|
|
332
|
+
(f"({fmt(plan.n_own)} own)" if self.opts.only_sources else
|
|
333
|
+
f"({fmt(plan.n_curated)} curated · {fmt(plan.n_meta)} from {plan.meta_ok}/{plan.meta_total} "
|
|
334
|
+
f"meta lists · {fmt(plan.n_discovered)} discovered"
|
|
335
|
+
+ (f" · {fmt(plan.n_own)} own)" if plan.n_own else ")"), MUTED),
|
|
332
336
|
))
|
|
333
337
|
if plan.discovery_ran and not plan.discovery_token:
|
|
334
338
|
note("GitHub discovery is limited without a token – run `gh auth login` or set GITHUB_TOKEN.",
|
|
@@ -355,7 +359,7 @@ class Run:
|
|
|
355
359
|
hosts = sorted(INSECURE_HOSTS)
|
|
356
360
|
note(f"Certificate could not be verified (TLS inspection on this network?), loaded anyway: "
|
|
357
361
|
f"{', '.join(hosts[:4])}{' …' if len(hosts) > 4 else ''}", MUTED, "ℹ")
|
|
358
|
-
return prioritize(res, self.quality, self.history, self.opts.types)
|
|
362
|
+
return prioritize(res, self.quality, self.history, self.opts.types, listed_only=self.opts.only_sources)
|
|
359
363
|
|
|
360
364
|
# ------------------------------------------------------------------ phase 3+4: check, learn, report
|
|
361
365
|
|
|
@@ -589,6 +593,9 @@ class Run:
|
|
|
589
593
|
note(f"{fmt(stats.blocklisted)} of {fmt(len(run.results))} hits ({share}) "
|
|
590
594
|
"exit from an IP on the SpamCop blocklist – sites that use it show captchas or block them. "
|
|
591
595
|
"Only the others: --no-blocklisted", MUTED, "ℹ")
|
|
596
|
+
if kept and opts.output != STDOUT and widgets.console.is_terminal and star_hint_due():
|
|
597
|
+
note("Found what you needed? A star on GitHub is how others find this: "
|
|
598
|
+
f"[link={REPO_URL}]{REPO_URL}[/link] [{MUTED}](shown once)[/]", ACCENT, "★")
|
|
592
599
|
if run.reached_goal:
|
|
593
600
|
note(f"Goal of {fmt(opts.want)} hits reached – stopped early.", GOOD, "✔")
|
|
594
601
|
elif run.interrupted:
|
|
@@ -246,6 +246,12 @@ def parse_args(argv: Optional[List[str]] = None) -> argparse.Namespace:
|
|
|
246
246
|
s.add_argument("--discover-repos", type=non_negative_int, default=DEFAULT_DISCOVER_REPOS,
|
|
247
247
|
help=f"max. repos during discovery (default: {DEFAULT_DISCOVER_REPOS}, 40 without a token)")
|
|
248
248
|
s.add_argument("--all-sources", action="store_true", help="also load dead, outdated and unreachable sources")
|
|
249
|
+
s.add_argument("--source", action="append", metavar="URL|FILE",
|
|
250
|
+
help="also load this proxy list (repeatable): a URL or a local file, one proxy per line or "
|
|
251
|
+
"any text with ip:port in it; TYPE=… fixes the type, e.g. socks5=https://…/list.txt – "
|
|
252
|
+
"without it, lines with a scheme keep theirs and bare ones are tried as HTTP and SOCKS5")
|
|
253
|
+
s.add_argument("--only-sources", action="store_true",
|
|
254
|
+
help="only the lists given with --source – no built-in, meta or discovered sources")
|
|
249
255
|
s.add_argument("--no-cache", action="store_true",
|
|
250
256
|
help="reload every list completely (otherwise unchanged ones are skipped via ETag)")
|
|
251
257
|
s.add_argument("--list-sources", nargs="?", const=50, type=positive_int, metavar="N",
|
|
@@ -115,6 +115,8 @@ class RunOptions:
|
|
|
115
115
|
no_discover: bool = False
|
|
116
116
|
discover_repos: int = DEFAULT_DISCOVER_REPOS
|
|
117
117
|
all_sources: bool = False
|
|
118
|
+
sources: List[str] = field(default_factory=list) # own lists (--source): URLs, files, 'socks5=…'
|
|
119
|
+
only_sources: bool = False # only the own lists – no curated, meta or discovered ones
|
|
118
120
|
no_cache: bool = False # reload every list instead of taking unchanged ones from the cache
|
|
119
121
|
no_dnsbl: bool = False # skip the blocklist lookup of the exit IPs
|
|
120
122
|
serve: int = 0 # port of the rotating proxy server after the run, 0 = off
|
|
@@ -149,6 +151,8 @@ class RunOptions:
|
|
|
149
151
|
raise ValueError("--sticky must not be negative")
|
|
150
152
|
if self.serve_refill < 0:
|
|
151
153
|
raise ValueError("--serve-refill must not be negative")
|
|
154
|
+
if self.only_sources and not self.sources:
|
|
155
|
+
raise ValueError("--only-sources needs at least one --source")
|
|
152
156
|
if not 0 <= self.serve <= 65535:
|
|
153
157
|
raise ValueError("port must be between 1 and 65535")
|
|
154
158
|
|
|
@@ -200,6 +204,8 @@ class RunOptions:
|
|
|
200
204
|
no_discover=args.no_discover,
|
|
201
205
|
discover_repos=args.discover_repos,
|
|
202
206
|
all_sources=args.all_sources,
|
|
207
|
+
sources=list(dict.fromkeys(args.source or [])),
|
|
208
|
+
only_sources=args.only_sources,
|
|
203
209
|
no_cache=args.no_cache,
|
|
204
210
|
no_dnsbl=args.no_dnsbl,
|
|
205
211
|
serve=args.serve,
|
|
@@ -245,6 +251,9 @@ class RunOptions:
|
|
|
245
251
|
_flag(argv, "--no-discover", self.no_discover)
|
|
246
252
|
_opt(argv, "--discover-repos", self.discover_repos, DEFAULT_DISCOVER_REPOS)
|
|
247
253
|
_flag(argv, "--all-sources", self.all_sources)
|
|
254
|
+
for spec in self.sources:
|
|
255
|
+
argv += ["--source", spec]
|
|
256
|
+
_flag(argv, "--only-sources", self.only_sources)
|
|
248
257
|
_flag(argv, "--no-cache", self.no_cache)
|
|
249
258
|
_flag(argv, "--no-dnsbl", self.no_dnsbl)
|
|
250
259
|
if self.serve:
|