proxy-scraper-cli 1.9.0__tar.gz → 1.11.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.9.0 → proxy_scraper_cli-1.11.0}/PKG-INFO +36 -14
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/README.md +34 -13
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxy_scraper_cli.egg-info/PKG-INFO +36 -14
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxy_scraper_cli.egg-info/SOURCES.txt +7 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxy_scraper_cli.egg-info/requires.txt +1 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/__init__.py +1 -1
- proxy_scraper_cli-1.11.0/proxyscraper/action.py +96 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/agent.py +7 -4
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/api.py +9 -5
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/cli.py +20 -5
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/completion.py +61 -3
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/exporters.py +43 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/mcp_server.py +11 -3
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/parsing.py +6 -1
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/proxypages.py +5 -1
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/publish.py +10 -4
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/report.py +66 -2
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/server/core.py +23 -11
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/site/index.html +168 -21
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/sites.py +55 -8
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/sources.py +8 -2
- proxy_scraper_cli-1.11.0/proxyscraper/speed.py +129 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/pyproject.toml +1 -1
- proxy_scraper_cli-1.11.0/tests/test_action.py +69 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_agent.py +1 -1
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_completion.py +35 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_exporters.py +22 -0
- proxy_scraper_cli-1.11.0/tests/test_parsing_fuzz.py +83 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_proxy_sources.py +29 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_report.py +49 -0
- proxy_scraper_cli-1.11.0/tests/test_server_closed_writer.py +72 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_sites.py +52 -5
- proxy_scraper_cli-1.11.0/tests/test_sources_json.py +36 -0
- proxy_scraper_cli-1.11.0/tests/test_speed.py +121 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/LICENSE +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxy_scraper_cli.egg-info/dependency_links.txt +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxy_scraper_cli.egg-info/entry_points.txt +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxy_scraper_cli.egg-info/top_level.txt +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/__main__.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/app.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/asndb.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/blocklist.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/charts.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/checker.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/compat.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/fetchcache.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/geo.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/geodb.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/handshake.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/history.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/judges.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/mcp_entry.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/netio.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/options.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/output.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/pages.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/paths.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/pipeline.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/preferences.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/server/__init__.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/server/http.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/server/pool.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/server/socks.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/server/status.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/server/upstream.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/site/apple-touch-icon.png +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/site/googleaac1161b7853c5b5.html +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/site/logo.png +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/site/og.png +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/sources.json +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/targets.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/ui/__init__.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/ui/dashboard.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/ui/keys.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/ui/report.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/ui/serve.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/ui/widgets.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/proxyscraper/ui/wizard.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/setup.cfg +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_api.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_app.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_asndb.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_auth.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_blocklist.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_charts.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_checker.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_compat.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_discovery_growth.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_fetchcache.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_geodb.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_judges.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_learning.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_live_api.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_mcp_server.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_mine_sources.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_options.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_output_stdout.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_packaging.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_pages.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_parsing.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_paths.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_pipeline.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_proxy_pages.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_publish.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_robustness.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_serve_password.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_serve_refill.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_serve_v2.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_server.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_server_fixes.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_tamper.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_targets.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_ui.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.0}/tests/test_uptime.py +0 -0
- {proxy_scraper_cli-1.9.0 → proxy_scraper_cli-1.11.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.11.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
|
|
@@ -35,6 +35,7 @@ Provides-Extra: mcp
|
|
|
35
35
|
Requires-Dist: mcp<3,>=2.2; python_version >= "3.10" and extra == "mcp"
|
|
36
36
|
Provides-Extra: dev
|
|
37
37
|
Requires-Dist: pytest; extra == "dev"
|
|
38
|
+
Requires-Dist: hypothesis; extra == "dev"
|
|
38
39
|
Requires-Dist: ruff==0.16.8; extra == "dev"
|
|
39
40
|
Dynamic: license-file
|
|
40
41
|
|
|
@@ -138,11 +139,12 @@ python3 proxy_scraper.py
|
|
|
138
139
|
|
|
139
140
|
Every [release](https://github.com/maximilianfeix/proxy-scraper/releases/latest) also ships a wheel you can install with `pip install <file>.whl`, and a multi-arch image (amd64/arm64) on `ghcr.io`. In the container the wizard never shows up, it runs straight away. For the proxy server use `--serve --serve-host 0.0.0.0` with `-p 127.0.0.1:8899:8899`, so the port is only open on your own machine.
|
|
140
141
|
|
|
141
|
-
Tab completion for bash, zsh and
|
|
142
|
+
Tab completion for bash, zsh, fish and PowerShell:
|
|
142
143
|
|
|
143
144
|
```bash
|
|
144
145
|
eval "$(proxy-scraper --completion zsh)" # in ~/.zshrc (after compinit), same for bash in ~/.bashrc
|
|
145
146
|
proxy-scraper --completion fish > ~/.config/fish/completions/proxy-scraper.fish
|
|
147
|
+
proxy-scraper --completion powershell | Out-String | Invoke-Expression # in $PROFILE
|
|
146
148
|
```
|
|
147
149
|
|
|
148
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.
|
|
@@ -203,7 +205,7 @@ Every protocol and country also has its own page with a plain download, e.g. [SO
|
|
|
203
205
|
| HTTP · SOCKS4 · SOCKS5 | `1.2.3.4:8080` | [http.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/http.txt) · [socks4.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/socks4.txt) · [socks5.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/socks5.txt) |
|
|
204
206
|
| HTTPS-capable only | `type://ip:port` | [https.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/https.txt) |
|
|
205
207
|
| Elite only | `type://ip:port` | [elite.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/elite.txt) |
|
|
206
|
-
| Gets through to Google · Reddit · Amazon (no captcha, no
|
|
208
|
+
| Gets through to Google · Reddit · Amazon · Instagram · TikTok (no captcha, no block in the last run) | `type://ip:port` | [google.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/google.txt) · [reddit.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/reddit.txt) · [amazon.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/amazon.txt) · [instagram.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/instagram.txt) · [tiktok.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/tiktok.txt) |
|
|
207
209
|
| Stable, on the list in 90 %+ of this week's runs | `type://ip:port` | [stable.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/stable.txt) |
|
|
208
210
|
| With all details | latency, country, HTTPS, anonymity, exit IP, uptime, sites | [proxies.json](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/proxies.json) · [proxies.csv](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/proxies.csv) |
|
|
209
211
|
|
|
@@ -217,6 +219,8 @@ Every protocol and country also has its own page with a plain download, e.g. [SO
|
|
|
217
219
|
curl -s https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/socks5.txt | head
|
|
218
220
|
```
|
|
219
221
|
|
|
222
|
+
**Over time:** every day the first run's `proxies.json` is kept for good as a gzipped asset of the release of that year, like [snapshots-2026](../../releases/tag/snapshots-2026) – `proxies-2026-09-28.json.gz` and so on, for anyone who wants to look at free proxies over weeks and months.
|
|
223
|
+
|
|
220
224
|
Every file is also on GitHub Pages, which sits behind a CDN, isn't rate limited like raw.githubusercontent and sends CORS headers, so it works straight from the browser: `https://maximilianfeix.github.io/proxy-scraper/socks5.txt`. [jsDelivr](https://cdn.jsdelivr.net/gh/maximilianfeix/proxy-scraper@proxy-list/) works too, but can lag behind by a few hours.
|
|
221
225
|
|
|
222
226
|
Or let the tool start from it: `proxy-scraper --recheck live` downloads the list and checks it again from **your** network – about 30 seconds instead of a full scan (517 of 1,169 worked from here). With `--serve` you have a rotating proxy in under a minute.
|
|
@@ -438,7 +442,7 @@ pool = itertools.cycle(p.url for p in proxies)
|
|
|
438
442
|
r = requests.get("https://api.ipify.org", proxies={"https": next(pool)}, timeout=15) # pip install "requests[socks]"
|
|
439
443
|
```
|
|
440
444
|
|
|
441
|
-
Same filters as `find_proxies`, plus `min_uptime`, `works_on` (`["google"]`, `"reddit"`, `"amazon"`) and `limit`. Every result also has `uptime_24h`, `uptime_7d`, `first_seen`, `up_for_hours` and `sites`.
|
|
445
|
+
Same filters as `find_proxies`, plus `min_uptime`, `works_on` (`["google"]`, `"reddit"`, `"amazon"`, `"instagram"`, `"tiktok"`) and `limit`. Every result also has `uptime_24h`, `uptime_7d`, `first_seen`, `up_for_hours` and `sites`.
|
|
442
446
|
|
|
443
447
|
<a id="proxy-server"></a>
|
|
444
448
|
|
|
@@ -656,14 +660,14 @@ if __name__ == "__main__":
|
|
|
656
660
|
|
|
657
661
|
In a Scrapy project, put `RotatingProxy` in `middlewares.py` and add it to `DOWNLOADER_MIDDLEWARES` in `settings.py`. For long crawls, reload the pool now and then – the list changes every hour.
|
|
658
662
|
|
|
659
|
-
**proxychains, Clash / Mihomo** – ready-made configs with `--export`
|
|
663
|
+
**proxychains, Clash / Mihomo, sing-box** – ready-made configs with `--export`
|
|
660
664
|
|
|
661
665
|
```bash
|
|
662
|
-
proxy-scraper --want 30 -y --export proxychains,clash
|
|
666
|
+
proxy-scraper --want 30 -y --export proxychains,clash,singbox
|
|
663
667
|
proxychains4 -f results/latest/proxychains.conf curl https://api.ipify.org
|
|
664
668
|
```
|
|
665
669
|
|
|
666
|
-
`clash.yaml` has all HTTP and SOCKS5 proxies plus a `url-test` group that always picks the fastest.
|
|
670
|
+
`clash.yaml` has all HTTP and SOCKS5 proxies plus a `url-test` group that always picks the fastest. `singbox.json` does the same for sing-box, SOCKS4 included, and opens a local proxy: `sing-box run -c results/latest/singbox.json`, then use `127.0.0.1:2080` as HTTP or SOCKS5 proxy. All three leave out HTTP proxies that can't tunnel (`CONNECT`), because these tools tunnel everything.
|
|
667
671
|
|
|
668
672
|
**In a pipe** – `-o -` prints the hits to stdout, the interface moves to stderr
|
|
669
673
|
|
|
@@ -679,6 +683,22 @@ export HTTPS_PROXY=http://127.0.0.1:8899 HTTP_PROXY=http://127.0.0.1:8899
|
|
|
679
683
|
pip download requests # git, pip, npm & co. now go through the pool
|
|
680
684
|
```
|
|
681
685
|
|
|
686
|
+
**In a GitHub workflow** – the action picks working proxies for the next steps
|
|
687
|
+
|
|
688
|
+
```yaml
|
|
689
|
+
- id: proxies
|
|
690
|
+
uses: maximilianfeix/proxy-scraper@v1
|
|
691
|
+
with:
|
|
692
|
+
types: socks5
|
|
693
|
+
https: true
|
|
694
|
+
min-uptime: 90 # on the list for 90 %+ of the week
|
|
695
|
+
works-on: google # optional: google, reddit, amazon
|
|
696
|
+
recheck: true # optional: check them again from the runner
|
|
697
|
+
- run: curl -x "${{ steps.proxies.outputs.proxy }}" https://api.ipify.org
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
`proxy` is the fastest one, `file` a text file with all of them (up to `limit`, default 20), `count` how many. Without a match the step fails, unless `fail-if-empty: false`.
|
|
701
|
+
|
|
682
702
|
**Without installing anything** – straight from the live list
|
|
683
703
|
|
|
684
704
|
```bash
|
|
@@ -722,16 +742,16 @@ curl.exe -x (Get-Content "$run\all.txt" -TotalCount 1) http://api.ipify.org
|
|
|
722
742
|
| `-t`, `--timeout S` | timeout per proxy (default: 8 s) |
|
|
723
743
|
| `--discover` | search GitHub for new sources right now |
|
|
724
744
|
| `--no-cache` | download every list again (unchanged ones are normally skipped via ETag) |
|
|
725
|
-
| `--list-sources [N]` | show the source ranking |
|
|
745
|
+
| `--list-sources [N]` | show the source ranking (add `--json` for scripts: url, status, hit rate, checks, last change) |
|
|
726
746
|
| `--serve-host ADDR` | where the proxy server listens (default `127.0.0.1`; `0.0.0.0` for Docker, with a warning) |
|
|
727
747
|
| `--serve-password SECRET` | clients must send this password in the proxy login; better set `PROXY_SCRAPER_SERVE_PASSWORD` |
|
|
728
748
|
| `--rotate STRATEGY` · `--sticky SEC` | how the proxy server picks proxies, see [above](#proxy-server) |
|
|
729
749
|
| `--serve-refill HOURS` | while serving, check fresh proxies every HOURS and add the hits to the pool |
|
|
730
750
|
| `--serve [PORT]` | afterwards serve as a rotating proxy on `127.0.0.1:PORT` (default: 8899) |
|
|
731
751
|
| `-o FILE` | also write all hits to this file; `-o -` prints them to stdout |
|
|
732
|
-
| `--export FORMATS` | extra files for other tools: `proxychains`, `clash`, `curl` or `all` |
|
|
752
|
+
| `--export FORMATS` | extra files for other tools: `proxychains`, `clash`, `singbox`, `curl` or `all` |
|
|
733
753
|
| `-V`, `--version` | print the version |
|
|
734
|
-
| `--completion SHELL` | print the tab completion script for bash, zsh or
|
|
754
|
+
| `--completion SHELL` | print the tab completion script for bash, zsh, fish or PowerShell |
|
|
735
755
|
|
|
736
756
|
Everything else: `proxy-scraper --help`
|
|
737
757
|
|
|
@@ -813,10 +833,12 @@ Only for things that don't matter. Public proxies are run by strangers who can r
|
|
|
813
833
|
|
|
814
834
|
## Roadmap
|
|
815
835
|
|
|
816
|
-
What's next is
|
|
836
|
+
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.
|
|
837
|
+
|
|
838
|
+
- [ ] [Measure throughput, not just latency](../../issues/140)
|
|
839
|
+
- [ ] [Daily snapshots as a dataset](../../issues/143)
|
|
817
840
|
|
|
818
|
-
|
|
819
|
-
- [ ] [sing-box export](../../issues/113), [PowerShell completion](../../issues/114), [shareable filters on the website](../../issues/116)
|
|
841
|
+
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.
|
|
820
842
|
|
|
821
843
|
Shipped in [v1.7](../../milestone/7): an MCP server so AI agents get working proxies and can load pages through them, 28 new sources and a GitHub search that runs daily and keeps what it found, and a cleaner website.
|
|
822
844
|
|
|
@@ -861,7 +883,7 @@ proxyscraper/
|
|
|
861
883
|
├── geodb.py DB-IP country database (monthly, binary search)
|
|
862
884
|
├── targets.py target sites for --target
|
|
863
885
|
├── output.py result files
|
|
864
|
-
├── exporters.py proxychains, Clash and curl formats (--export)
|
|
886
|
+
├── exporters.py proxychains, Clash, sing-box and curl formats (--export)
|
|
865
887
|
├── server/ rotating proxy server (--serve): pool · http · upstream · socks · status · core
|
|
866
888
|
├── api.py find_proxies() / check_proxies() for Python
|
|
867
889
|
├── agent.py MCP tools without the SDK: live list, filters, fetch through proxies
|
|
@@ -98,11 +98,12 @@ python3 proxy_scraper.py
|
|
|
98
98
|
|
|
99
99
|
Every [release](https://github.com/maximilianfeix/proxy-scraper/releases/latest) also ships a wheel you can install with `pip install <file>.whl`, and a multi-arch image (amd64/arm64) on `ghcr.io`. In the container the wizard never shows up, it runs straight away. For the proxy server use `--serve --serve-host 0.0.0.0` with `-p 127.0.0.1:8899:8899`, so the port is only open on your own machine.
|
|
100
100
|
|
|
101
|
-
Tab completion for bash, zsh and
|
|
101
|
+
Tab completion for bash, zsh, fish and PowerShell:
|
|
102
102
|
|
|
103
103
|
```bash
|
|
104
104
|
eval "$(proxy-scraper --completion zsh)" # in ~/.zshrc (after compinit), same for bash in ~/.bashrc
|
|
105
105
|
proxy-scraper --completion fish > ~/.config/fish/completions/proxy-scraper.fish
|
|
106
|
+
proxy-scraper --completion powershell | Out-String | Invoke-Expression # in $PROFILE
|
|
106
107
|
```
|
|
107
108
|
|
|
108
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.
|
|
@@ -163,7 +164,7 @@ Every protocol and country also has its own page with a plain download, e.g. [SO
|
|
|
163
164
|
| HTTP · SOCKS4 · SOCKS5 | `1.2.3.4:8080` | [http.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/http.txt) · [socks4.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/socks4.txt) · [socks5.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/socks5.txt) |
|
|
164
165
|
| HTTPS-capable only | `type://ip:port` | [https.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/https.txt) |
|
|
165
166
|
| Elite only | `type://ip:port` | [elite.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/elite.txt) |
|
|
166
|
-
| Gets through to Google · Reddit · Amazon (no captcha, no
|
|
167
|
+
| Gets through to Google · Reddit · Amazon · Instagram · TikTok (no captcha, no block in the last run) | `type://ip:port` | [google.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/google.txt) · [reddit.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/reddit.txt) · [amazon.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/amazon.txt) · [instagram.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/instagram.txt) · [tiktok.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/tiktok.txt) |
|
|
167
168
|
| Stable, on the list in 90 %+ of this week's runs | `type://ip:port` | [stable.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/stable.txt) |
|
|
168
169
|
| With all details | latency, country, HTTPS, anonymity, exit IP, uptime, sites | [proxies.json](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/proxies.json) · [proxies.csv](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/proxies.csv) |
|
|
169
170
|
|
|
@@ -177,6 +178,8 @@ Every protocol and country also has its own page with a plain download, e.g. [SO
|
|
|
177
178
|
curl -s https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/socks5.txt | head
|
|
178
179
|
```
|
|
179
180
|
|
|
181
|
+
**Over time:** every day the first run's `proxies.json` is kept for good as a gzipped asset of the release of that year, like [snapshots-2026](../../releases/tag/snapshots-2026) – `proxies-2026-09-28.json.gz` and so on, for anyone who wants to look at free proxies over weeks and months.
|
|
182
|
+
|
|
180
183
|
Every file is also on GitHub Pages, which sits behind a CDN, isn't rate limited like raw.githubusercontent and sends CORS headers, so it works straight from the browser: `https://maximilianfeix.github.io/proxy-scraper/socks5.txt`. [jsDelivr](https://cdn.jsdelivr.net/gh/maximilianfeix/proxy-scraper@proxy-list/) works too, but can lag behind by a few hours.
|
|
181
184
|
|
|
182
185
|
Or let the tool start from it: `proxy-scraper --recheck live` downloads the list and checks it again from **your** network – about 30 seconds instead of a full scan (517 of 1,169 worked from here). With `--serve` you have a rotating proxy in under a minute.
|
|
@@ -398,7 +401,7 @@ pool = itertools.cycle(p.url for p in proxies)
|
|
|
398
401
|
r = requests.get("https://api.ipify.org", proxies={"https": next(pool)}, timeout=15) # pip install "requests[socks]"
|
|
399
402
|
```
|
|
400
403
|
|
|
401
|
-
Same filters as `find_proxies`, plus `min_uptime`, `works_on` (`["google"]`, `"reddit"`, `"amazon"`) and `limit`. Every result also has `uptime_24h`, `uptime_7d`, `first_seen`, `up_for_hours` and `sites`.
|
|
404
|
+
Same filters as `find_proxies`, plus `min_uptime`, `works_on` (`["google"]`, `"reddit"`, `"amazon"`, `"instagram"`, `"tiktok"`) and `limit`. Every result also has `uptime_24h`, `uptime_7d`, `first_seen`, `up_for_hours` and `sites`.
|
|
402
405
|
|
|
403
406
|
<a id="proxy-server"></a>
|
|
404
407
|
|
|
@@ -616,14 +619,14 @@ if __name__ == "__main__":
|
|
|
616
619
|
|
|
617
620
|
In a Scrapy project, put `RotatingProxy` in `middlewares.py` and add it to `DOWNLOADER_MIDDLEWARES` in `settings.py`. For long crawls, reload the pool now and then – the list changes every hour.
|
|
618
621
|
|
|
619
|
-
**proxychains, Clash / Mihomo** – ready-made configs with `--export`
|
|
622
|
+
**proxychains, Clash / Mihomo, sing-box** – ready-made configs with `--export`
|
|
620
623
|
|
|
621
624
|
```bash
|
|
622
|
-
proxy-scraper --want 30 -y --export proxychains,clash
|
|
625
|
+
proxy-scraper --want 30 -y --export proxychains,clash,singbox
|
|
623
626
|
proxychains4 -f results/latest/proxychains.conf curl https://api.ipify.org
|
|
624
627
|
```
|
|
625
628
|
|
|
626
|
-
`clash.yaml` has all HTTP and SOCKS5 proxies plus a `url-test` group that always picks the fastest.
|
|
629
|
+
`clash.yaml` has all HTTP and SOCKS5 proxies plus a `url-test` group that always picks the fastest. `singbox.json` does the same for sing-box, SOCKS4 included, and opens a local proxy: `sing-box run -c results/latest/singbox.json`, then use `127.0.0.1:2080` as HTTP or SOCKS5 proxy. All three leave out HTTP proxies that can't tunnel (`CONNECT`), because these tools tunnel everything.
|
|
627
630
|
|
|
628
631
|
**In a pipe** – `-o -` prints the hits to stdout, the interface moves to stderr
|
|
629
632
|
|
|
@@ -639,6 +642,22 @@ export HTTPS_PROXY=http://127.0.0.1:8899 HTTP_PROXY=http://127.0.0.1:8899
|
|
|
639
642
|
pip download requests # git, pip, npm & co. now go through the pool
|
|
640
643
|
```
|
|
641
644
|
|
|
645
|
+
**In a GitHub workflow** – the action picks working proxies for the next steps
|
|
646
|
+
|
|
647
|
+
```yaml
|
|
648
|
+
- id: proxies
|
|
649
|
+
uses: maximilianfeix/proxy-scraper@v1
|
|
650
|
+
with:
|
|
651
|
+
types: socks5
|
|
652
|
+
https: true
|
|
653
|
+
min-uptime: 90 # on the list for 90 %+ of the week
|
|
654
|
+
works-on: google # optional: google, reddit, amazon
|
|
655
|
+
recheck: true # optional: check them again from the runner
|
|
656
|
+
- run: curl -x "${{ steps.proxies.outputs.proxy }}" https://api.ipify.org
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
`proxy` is the fastest one, `file` a text file with all of them (up to `limit`, default 20), `count` how many. Without a match the step fails, unless `fail-if-empty: false`.
|
|
660
|
+
|
|
642
661
|
**Without installing anything** – straight from the live list
|
|
643
662
|
|
|
644
663
|
```bash
|
|
@@ -682,16 +701,16 @@ curl.exe -x (Get-Content "$run\all.txt" -TotalCount 1) http://api.ipify.org
|
|
|
682
701
|
| `-t`, `--timeout S` | timeout per proxy (default: 8 s) |
|
|
683
702
|
| `--discover` | search GitHub for new sources right now |
|
|
684
703
|
| `--no-cache` | download every list again (unchanged ones are normally skipped via ETag) |
|
|
685
|
-
| `--list-sources [N]` | show the source ranking |
|
|
704
|
+
| `--list-sources [N]` | show the source ranking (add `--json` for scripts: url, status, hit rate, checks, last change) |
|
|
686
705
|
| `--serve-host ADDR` | where the proxy server listens (default `127.0.0.1`; `0.0.0.0` for Docker, with a warning) |
|
|
687
706
|
| `--serve-password SECRET` | clients must send this password in the proxy login; better set `PROXY_SCRAPER_SERVE_PASSWORD` |
|
|
688
707
|
| `--rotate STRATEGY` · `--sticky SEC` | how the proxy server picks proxies, see [above](#proxy-server) |
|
|
689
708
|
| `--serve-refill HOURS` | while serving, check fresh proxies every HOURS and add the hits to the pool |
|
|
690
709
|
| `--serve [PORT]` | afterwards serve as a rotating proxy on `127.0.0.1:PORT` (default: 8899) |
|
|
691
710
|
| `-o FILE` | also write all hits to this file; `-o -` prints them to stdout |
|
|
692
|
-
| `--export FORMATS` | extra files for other tools: `proxychains`, `clash`, `curl` or `all` |
|
|
711
|
+
| `--export FORMATS` | extra files for other tools: `proxychains`, `clash`, `singbox`, `curl` or `all` |
|
|
693
712
|
| `-V`, `--version` | print the version |
|
|
694
|
-
| `--completion SHELL` | print the tab completion script for bash, zsh or
|
|
713
|
+
| `--completion SHELL` | print the tab completion script for bash, zsh, fish or PowerShell |
|
|
695
714
|
|
|
696
715
|
Everything else: `proxy-scraper --help`
|
|
697
716
|
|
|
@@ -773,10 +792,12 @@ Only for things that don't matter. Public proxies are run by strangers who can r
|
|
|
773
792
|
|
|
774
793
|
## Roadmap
|
|
775
794
|
|
|
776
|
-
What's next is
|
|
795
|
+
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.
|
|
796
|
+
|
|
797
|
+
- [ ] [Measure throughput, not just latency](../../issues/140)
|
|
798
|
+
- [ ] [Daily snapshots as a dataset](../../issues/143)
|
|
777
799
|
|
|
778
|
-
|
|
779
|
-
- [ ] [sing-box export](../../issues/113), [PowerShell completion](../../issues/114), [shareable filters on the website](../../issues/116)
|
|
800
|
+
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.
|
|
780
801
|
|
|
781
802
|
Shipped in [v1.7](../../milestone/7): an MCP server so AI agents get working proxies and can load pages through them, 28 new sources and a GitHub search that runs daily and keeps what it found, and a cleaner website.
|
|
782
803
|
|
|
@@ -821,7 +842,7 @@ proxyscraper/
|
|
|
821
842
|
├── geodb.py DB-IP country database (monthly, binary search)
|
|
822
843
|
├── targets.py target sites for --target
|
|
823
844
|
├── output.py result files
|
|
824
|
-
├── exporters.py proxychains, Clash and curl formats (--export)
|
|
845
|
+
├── exporters.py proxychains, Clash, sing-box and curl formats (--export)
|
|
825
846
|
├── server/ rotating proxy server (--serve): pool · http · upstream · socks · status · core
|
|
826
847
|
├── api.py find_proxies() / check_proxies() for Python
|
|
827
848
|
├── agent.py MCP tools without the SDK: live list, filters, fetch through proxies
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: proxy-scraper-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.11.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
|
|
@@ -35,6 +35,7 @@ Provides-Extra: mcp
|
|
|
35
35
|
Requires-Dist: mcp<3,>=2.2; python_version >= "3.10" and extra == "mcp"
|
|
36
36
|
Provides-Extra: dev
|
|
37
37
|
Requires-Dist: pytest; extra == "dev"
|
|
38
|
+
Requires-Dist: hypothesis; extra == "dev"
|
|
38
39
|
Requires-Dist: ruff==0.16.8; extra == "dev"
|
|
39
40
|
Dynamic: license-file
|
|
40
41
|
|
|
@@ -138,11 +139,12 @@ python3 proxy_scraper.py
|
|
|
138
139
|
|
|
139
140
|
Every [release](https://github.com/maximilianfeix/proxy-scraper/releases/latest) also ships a wheel you can install with `pip install <file>.whl`, and a multi-arch image (amd64/arm64) on `ghcr.io`. In the container the wizard never shows up, it runs straight away. For the proxy server use `--serve --serve-host 0.0.0.0` with `-p 127.0.0.1:8899:8899`, so the port is only open on your own machine.
|
|
140
141
|
|
|
141
|
-
Tab completion for bash, zsh and
|
|
142
|
+
Tab completion for bash, zsh, fish and PowerShell:
|
|
142
143
|
|
|
143
144
|
```bash
|
|
144
145
|
eval "$(proxy-scraper --completion zsh)" # in ~/.zshrc (after compinit), same for bash in ~/.bashrc
|
|
145
146
|
proxy-scraper --completion fish > ~/.config/fish/completions/proxy-scraper.fish
|
|
147
|
+
proxy-scraper --completion powershell | Out-String | Invoke-Expression # in $PROFILE
|
|
146
148
|
```
|
|
147
149
|
|
|
148
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.
|
|
@@ -203,7 +205,7 @@ Every protocol and country also has its own page with a plain download, e.g. [SO
|
|
|
203
205
|
| HTTP · SOCKS4 · SOCKS5 | `1.2.3.4:8080` | [http.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/http.txt) · [socks4.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/socks4.txt) · [socks5.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/socks5.txt) |
|
|
204
206
|
| HTTPS-capable only | `type://ip:port` | [https.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/https.txt) |
|
|
205
207
|
| Elite only | `type://ip:port` | [elite.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/elite.txt) |
|
|
206
|
-
| Gets through to Google · Reddit · Amazon (no captcha, no
|
|
208
|
+
| Gets through to Google · Reddit · Amazon · Instagram · TikTok (no captcha, no block in the last run) | `type://ip:port` | [google.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/google.txt) · [reddit.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/reddit.txt) · [amazon.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/amazon.txt) · [instagram.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/instagram.txt) · [tiktok.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/tiktok.txt) |
|
|
207
209
|
| Stable, on the list in 90 %+ of this week's runs | `type://ip:port` | [stable.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/stable.txt) |
|
|
208
210
|
| With all details | latency, country, HTTPS, anonymity, exit IP, uptime, sites | [proxies.json](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/proxies.json) · [proxies.csv](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/proxies.csv) |
|
|
209
211
|
|
|
@@ -217,6 +219,8 @@ Every protocol and country also has its own page with a plain download, e.g. [SO
|
|
|
217
219
|
curl -s https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/socks5.txt | head
|
|
218
220
|
```
|
|
219
221
|
|
|
222
|
+
**Over time:** every day the first run's `proxies.json` is kept for good as a gzipped asset of the release of that year, like [snapshots-2026](../../releases/tag/snapshots-2026) – `proxies-2026-09-28.json.gz` and so on, for anyone who wants to look at free proxies over weeks and months.
|
|
223
|
+
|
|
220
224
|
Every file is also on GitHub Pages, which sits behind a CDN, isn't rate limited like raw.githubusercontent and sends CORS headers, so it works straight from the browser: `https://maximilianfeix.github.io/proxy-scraper/socks5.txt`. [jsDelivr](https://cdn.jsdelivr.net/gh/maximilianfeix/proxy-scraper@proxy-list/) works too, but can lag behind by a few hours.
|
|
221
225
|
|
|
222
226
|
Or let the tool start from it: `proxy-scraper --recheck live` downloads the list and checks it again from **your** network – about 30 seconds instead of a full scan (517 of 1,169 worked from here). With `--serve` you have a rotating proxy in under a minute.
|
|
@@ -438,7 +442,7 @@ pool = itertools.cycle(p.url for p in proxies)
|
|
|
438
442
|
r = requests.get("https://api.ipify.org", proxies={"https": next(pool)}, timeout=15) # pip install "requests[socks]"
|
|
439
443
|
```
|
|
440
444
|
|
|
441
|
-
Same filters as `find_proxies`, plus `min_uptime`, `works_on` (`["google"]`, `"reddit"`, `"amazon"`) and `limit`. Every result also has `uptime_24h`, `uptime_7d`, `first_seen`, `up_for_hours` and `sites`.
|
|
445
|
+
Same filters as `find_proxies`, plus `min_uptime`, `works_on` (`["google"]`, `"reddit"`, `"amazon"`, `"instagram"`, `"tiktok"`) and `limit`. Every result also has `uptime_24h`, `uptime_7d`, `first_seen`, `up_for_hours` and `sites`.
|
|
442
446
|
|
|
443
447
|
<a id="proxy-server"></a>
|
|
444
448
|
|
|
@@ -656,14 +660,14 @@ if __name__ == "__main__":
|
|
|
656
660
|
|
|
657
661
|
In a Scrapy project, put `RotatingProxy` in `middlewares.py` and add it to `DOWNLOADER_MIDDLEWARES` in `settings.py`. For long crawls, reload the pool now and then – the list changes every hour.
|
|
658
662
|
|
|
659
|
-
**proxychains, Clash / Mihomo** – ready-made configs with `--export`
|
|
663
|
+
**proxychains, Clash / Mihomo, sing-box** – ready-made configs with `--export`
|
|
660
664
|
|
|
661
665
|
```bash
|
|
662
|
-
proxy-scraper --want 30 -y --export proxychains,clash
|
|
666
|
+
proxy-scraper --want 30 -y --export proxychains,clash,singbox
|
|
663
667
|
proxychains4 -f results/latest/proxychains.conf curl https://api.ipify.org
|
|
664
668
|
```
|
|
665
669
|
|
|
666
|
-
`clash.yaml` has all HTTP and SOCKS5 proxies plus a `url-test` group that always picks the fastest.
|
|
670
|
+
`clash.yaml` has all HTTP and SOCKS5 proxies plus a `url-test` group that always picks the fastest. `singbox.json` does the same for sing-box, SOCKS4 included, and opens a local proxy: `sing-box run -c results/latest/singbox.json`, then use `127.0.0.1:2080` as HTTP or SOCKS5 proxy. All three leave out HTTP proxies that can't tunnel (`CONNECT`), because these tools tunnel everything.
|
|
667
671
|
|
|
668
672
|
**In a pipe** – `-o -` prints the hits to stdout, the interface moves to stderr
|
|
669
673
|
|
|
@@ -679,6 +683,22 @@ export HTTPS_PROXY=http://127.0.0.1:8899 HTTP_PROXY=http://127.0.0.1:8899
|
|
|
679
683
|
pip download requests # git, pip, npm & co. now go through the pool
|
|
680
684
|
```
|
|
681
685
|
|
|
686
|
+
**In a GitHub workflow** – the action picks working proxies for the next steps
|
|
687
|
+
|
|
688
|
+
```yaml
|
|
689
|
+
- id: proxies
|
|
690
|
+
uses: maximilianfeix/proxy-scraper@v1
|
|
691
|
+
with:
|
|
692
|
+
types: socks5
|
|
693
|
+
https: true
|
|
694
|
+
min-uptime: 90 # on the list for 90 %+ of the week
|
|
695
|
+
works-on: google # optional: google, reddit, amazon
|
|
696
|
+
recheck: true # optional: check them again from the runner
|
|
697
|
+
- run: curl -x "${{ steps.proxies.outputs.proxy }}" https://api.ipify.org
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
`proxy` is the fastest one, `file` a text file with all of them (up to `limit`, default 20), `count` how many. Without a match the step fails, unless `fail-if-empty: false`.
|
|
701
|
+
|
|
682
702
|
**Without installing anything** – straight from the live list
|
|
683
703
|
|
|
684
704
|
```bash
|
|
@@ -722,16 +742,16 @@ curl.exe -x (Get-Content "$run\all.txt" -TotalCount 1) http://api.ipify.org
|
|
|
722
742
|
| `-t`, `--timeout S` | timeout per proxy (default: 8 s) |
|
|
723
743
|
| `--discover` | search GitHub for new sources right now |
|
|
724
744
|
| `--no-cache` | download every list again (unchanged ones are normally skipped via ETag) |
|
|
725
|
-
| `--list-sources [N]` | show the source ranking |
|
|
745
|
+
| `--list-sources [N]` | show the source ranking (add `--json` for scripts: url, status, hit rate, checks, last change) |
|
|
726
746
|
| `--serve-host ADDR` | where the proxy server listens (default `127.0.0.1`; `0.0.0.0` for Docker, with a warning) |
|
|
727
747
|
| `--serve-password SECRET` | clients must send this password in the proxy login; better set `PROXY_SCRAPER_SERVE_PASSWORD` |
|
|
728
748
|
| `--rotate STRATEGY` · `--sticky SEC` | how the proxy server picks proxies, see [above](#proxy-server) |
|
|
729
749
|
| `--serve-refill HOURS` | while serving, check fresh proxies every HOURS and add the hits to the pool |
|
|
730
750
|
| `--serve [PORT]` | afterwards serve as a rotating proxy on `127.0.0.1:PORT` (default: 8899) |
|
|
731
751
|
| `-o FILE` | also write all hits to this file; `-o -` prints them to stdout |
|
|
732
|
-
| `--export FORMATS` | extra files for other tools: `proxychains`, `clash`, `curl` or `all` |
|
|
752
|
+
| `--export FORMATS` | extra files for other tools: `proxychains`, `clash`, `singbox`, `curl` or `all` |
|
|
733
753
|
| `-V`, `--version` | print the version |
|
|
734
|
-
| `--completion SHELL` | print the tab completion script for bash, zsh or
|
|
754
|
+
| `--completion SHELL` | print the tab completion script for bash, zsh, fish or PowerShell |
|
|
735
755
|
|
|
736
756
|
Everything else: `proxy-scraper --help`
|
|
737
757
|
|
|
@@ -813,10 +833,12 @@ Only for things that don't matter. Public proxies are run by strangers who can r
|
|
|
813
833
|
|
|
814
834
|
## Roadmap
|
|
815
835
|
|
|
816
|
-
What's next is
|
|
836
|
+
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.
|
|
837
|
+
|
|
838
|
+
- [ ] [Measure throughput, not just latency](../../issues/140)
|
|
839
|
+
- [ ] [Daily snapshots as a dataset](../../issues/143)
|
|
817
840
|
|
|
818
|
-
|
|
819
|
-
- [ ] [sing-box export](../../issues/113), [PowerShell completion](../../issues/114), [shareable filters on the website](../../issues/116)
|
|
841
|
+
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.
|
|
820
842
|
|
|
821
843
|
Shipped in [v1.7](../../milestone/7): an MCP server so AI agents get working proxies and can load pages through them, 28 new sources and a GitHub search that runs daily and keeps what it found, and a cleaner website.
|
|
822
844
|
|
|
@@ -861,7 +883,7 @@ proxyscraper/
|
|
|
861
883
|
├── geodb.py DB-IP country database (monthly, binary search)
|
|
862
884
|
├── targets.py target sites for --target
|
|
863
885
|
├── output.py result files
|
|
864
|
-
├── exporters.py proxychains, Clash and curl formats (--export)
|
|
886
|
+
├── exporters.py proxychains, Clash, sing-box and curl formats (--export)
|
|
865
887
|
├── server/ rotating proxy server (--serve): pool · http · upstream · socks · status · core
|
|
866
888
|
├── api.py find_proxies() / check_proxies() for Python
|
|
867
889
|
├── agent.py MCP tools without the SDK: live list, filters, fetch through proxies
|
|
@@ -9,6 +9,7 @@ proxy_scraper_cli.egg-info/requires.txt
|
|
|
9
9
|
proxy_scraper_cli.egg-info/top_level.txt
|
|
10
10
|
proxyscraper/__init__.py
|
|
11
11
|
proxyscraper/__main__.py
|
|
12
|
+
proxyscraper/action.py
|
|
12
13
|
proxyscraper/agent.py
|
|
13
14
|
proxyscraper/api.py
|
|
14
15
|
proxyscraper/app.py
|
|
@@ -42,6 +43,7 @@ proxyscraper/report.py
|
|
|
42
43
|
proxyscraper/sites.py
|
|
43
44
|
proxyscraper/sources.json
|
|
44
45
|
proxyscraper/sources.py
|
|
46
|
+
proxyscraper/speed.py
|
|
45
47
|
proxyscraper/targets.py
|
|
46
48
|
proxyscraper/server/__init__.py
|
|
47
49
|
proxyscraper/server/core.py
|
|
@@ -62,6 +64,7 @@ proxyscraper/ui/report.py
|
|
|
62
64
|
proxyscraper/ui/serve.py
|
|
63
65
|
proxyscraper/ui/widgets.py
|
|
64
66
|
proxyscraper/ui/wizard.py
|
|
67
|
+
tests/test_action.py
|
|
65
68
|
tests/test_agent.py
|
|
66
69
|
tests/test_api.py
|
|
67
70
|
tests/test_app.py
|
|
@@ -86,6 +89,7 @@ tests/test_output_stdout.py
|
|
|
86
89
|
tests/test_packaging.py
|
|
87
90
|
tests/test_pages.py
|
|
88
91
|
tests/test_parsing.py
|
|
92
|
+
tests/test_parsing_fuzz.py
|
|
89
93
|
tests/test_paths.py
|
|
90
94
|
tests/test_pipeline.py
|
|
91
95
|
tests/test_proxy_pages.py
|
|
@@ -97,8 +101,11 @@ tests/test_serve_password.py
|
|
|
97
101
|
tests/test_serve_refill.py
|
|
98
102
|
tests/test_serve_v2.py
|
|
99
103
|
tests/test_server.py
|
|
104
|
+
tests/test_server_closed_writer.py
|
|
100
105
|
tests/test_server_fixes.py
|
|
101
106
|
tests/test_sites.py
|
|
107
|
+
tests/test_sources_json.py
|
|
108
|
+
tests/test_speed.py
|
|
102
109
|
tests/test_tamper.py
|
|
103
110
|
tests/test_targets.py
|
|
104
111
|
tests/test_ui.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.11.0"
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def __getattr__(name):
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""The GitHub Action (action.yml): working proxies from the hourly list for the next steps of a workflow.
|
|
2
|
+
|
|
3
|
+
Inputs come in as PS_* environment variables, results go to $GITHUB_OUTPUT:
|
|
4
|
+
proxy the fastest one, ready to use (socks5://1.2.3.4:1080)
|
|
5
|
+
file a text file with all of them, one per line, fastest first
|
|
6
|
+
count how many
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import sys
|
|
13
|
+
import tempfile
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import List
|
|
16
|
+
|
|
17
|
+
from .api import check_proxies, live_proxies
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class InputError(ValueError):
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _flag(name: str, default: bool = False) -> bool:
|
|
25
|
+
value = os.environ.get(name, "").strip().lower()
|
|
26
|
+
if not value:
|
|
27
|
+
return default
|
|
28
|
+
if value in ("true", "yes", "1"):
|
|
29
|
+
return True
|
|
30
|
+
if value in ("false", "no", "0"):
|
|
31
|
+
return False
|
|
32
|
+
raise InputError(f"{name[3:].lower().replace('_', '-')} must be true or false, not {value!r}")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _number(name: str, default: int) -> int:
|
|
36
|
+
value = os.environ.get(name, "").strip()
|
|
37
|
+
if not value:
|
|
38
|
+
return default
|
|
39
|
+
if not value.isdigit():
|
|
40
|
+
raise InputError(f"{name[3:].lower().replace('_', '-')} must be a whole number, not {value!r}")
|
|
41
|
+
return int(value)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _list(name: str) -> List[str]:
|
|
45
|
+
return [part.strip().lower() for part in os.environ.get(name, "").split(",") if part.strip()]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _output(**values: str) -> None:
|
|
49
|
+
path = os.environ.get("GITHUB_OUTPUT")
|
|
50
|
+
lines = "".join(f"{key}={value}\n" for key, value in values.items())
|
|
51
|
+
if path:
|
|
52
|
+
with open(path, "a", encoding="utf-8") as fh:
|
|
53
|
+
fh.write(lines)
|
|
54
|
+
else:
|
|
55
|
+
sys.stdout.write(lines)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def main() -> int:
|
|
59
|
+
try:
|
|
60
|
+
limit = _number("PS_LIMIT", 20)
|
|
61
|
+
recheck = _flag("PS_RECHECK")
|
|
62
|
+
fail_if_empty = _flag("PS_FAIL_IF_EMPTY", True)
|
|
63
|
+
filters = {"types": _list("PS_TYPES") or ["http", "socks4", "socks5"],
|
|
64
|
+
"countries": os.environ.get("PS_COUNTRIES", "").strip(),
|
|
65
|
+
"https": _flag("PS_HTTPS"), "min_uptime": _number("PS_MIN_UPTIME", 0),
|
|
66
|
+
"works_on": _list("PS_WORKS_ON")}
|
|
67
|
+
# a recheck starts from all of them – the limit applies to what still works from here
|
|
68
|
+
found = live_proxies(**filters, limit=0 if recheck else limit)
|
|
69
|
+
except (InputError, ValueError) as e:
|
|
70
|
+
print(f"::error::{e}")
|
|
71
|
+
return 1
|
|
72
|
+
except ConnectionError as e:
|
|
73
|
+
print(f"::error::The live list couldn't be loaded: {e}")
|
|
74
|
+
return 1
|
|
75
|
+
urls = [p.url for p in found]
|
|
76
|
+
if recheck and urls:
|
|
77
|
+
print(f"Checking {len(urls)} proxies again from this runner …")
|
|
78
|
+
urls = [r.url for r in sorted(check_proxies(urls, https=filters["https"]), key=lambda r: r.latency)]
|
|
79
|
+
if limit:
|
|
80
|
+
urls = urls[:limit]
|
|
81
|
+
# a file of its own per step: a job may use the action twice (socks5 in one step, http in the next)
|
|
82
|
+
fd, name = tempfile.mkstemp(prefix="proxies-", suffix=".txt", dir=os.environ.get("RUNNER_TEMP") or None)
|
|
83
|
+
with os.fdopen(fd, "w", encoding="utf-8") as fh:
|
|
84
|
+
fh.write("".join(f"{u}\n" for u in urls))
|
|
85
|
+
file = Path(name)
|
|
86
|
+
_output(proxy=urls[0] if urls else "", file=str(file), count=str(len(urls)))
|
|
87
|
+
print(f"{len(urls)} working {'proxy' if len(urls) == 1 else 'proxies'}" + (f", fastest: {urls[0]}" if urls else ""))
|
|
88
|
+
if not urls and fail_if_empty:
|
|
89
|
+
print("::error::No proxy matches these filters right now – loosen them (min-uptime, works-on, countries) "
|
|
90
|
+
"or set fail-if-empty: false")
|
|
91
|
+
return 1
|
|
92
|
+
return 0
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
if __name__ == "__main__":
|
|
96
|
+
sys.exit(main())
|
|
@@ -179,17 +179,18 @@ def normalize_countries(countries: Iterable[str]) -> List[str]:
|
|
|
179
179
|
def select(rows: Iterable[dict], protocol: str = "any", countries: Iterable[str] = (), https_only: bool = False,
|
|
180
180
|
elite_only: bool = False, exclude_datacenter: bool = False, exclude_blocklisted: bool = False,
|
|
181
181
|
stable_only: bool = False, max_latency_ms: int = 0, run_hours: int = 1, min_uptime: int = 0,
|
|
182
|
-
works_on: Iterable[str] = ()) -> List[dict]:
|
|
182
|
+
works_on: Iterable[str] = (), min_speed_kbps: int = 0) -> List[dict]:
|
|
183
183
|
"""The rows that pass every filter, fastest first – the same filters as on the website."""
|
|
184
184
|
return sorted(matching(rows, protocol, countries, https_only, elite_only, exclude_datacenter,
|
|
185
|
-
exclude_blocklisted, stable_only, max_latency_ms, run_hours, min_uptime, works_on
|
|
185
|
+
exclude_blocklisted, stable_only, max_latency_ms, run_hours, min_uptime, works_on,
|
|
186
|
+
min_speed_kbps),
|
|
186
187
|
key=lambda r: r.get("latency") or 0)
|
|
187
188
|
|
|
188
189
|
|
|
189
190
|
def matching(rows: Iterable[dict], protocol: str = "any", countries: Iterable[str] = (), https_only: bool = False,
|
|
190
191
|
elite_only: bool = False, exclude_datacenter: bool = False, exclude_blocklisted: bool = False,
|
|
191
192
|
stable_only: bool = False, max_latency_ms: int = 0, run_hours: int = 1,
|
|
192
|
-
min_uptime: int = 0, works_on: Iterable[str] = ()) -> Iterator[dict]:
|
|
193
|
+
min_uptime: int = 0, works_on: Iterable[str] = (), min_speed_kbps: int = 0) -> Iterator[dict]:
|
|
193
194
|
"""The rows that pass every filter, in list order – checks the filters before the first row is asked for."""
|
|
194
195
|
protocol = _check_protocol(protocol)
|
|
195
196
|
wanted = set(normalize_countries(countries))
|
|
@@ -205,7 +206,8 @@ def matching(rows: Iterable[dict], protocol: str = "any", countries: Iterable[st
|
|
|
205
206
|
and (not stable_only or (r.get("streak") or 0) >= stable_runs)
|
|
206
207
|
and (not max_latency_ms or (r.get("latency") or 0) <= max_latency_ms)
|
|
207
208
|
and (not min_uptime or (r.get("uptime_7d") or 0) >= min_uptime)
|
|
208
|
-
and all((r.get("sites") or {}).get(s) for s in sites)
|
|
209
|
+
and all((r.get("sites") or {}).get(s) for s in sites)
|
|
210
|
+
and (not min_speed_kbps or (r.get("speed_kbps") or 0) >= min_speed_kbps))
|
|
209
211
|
|
|
210
212
|
|
|
211
213
|
def describe(item: Union[dict, CheckResult], run_hours: Optional[int] = None) -> dict:
|
|
@@ -229,6 +231,7 @@ def describe(item: Union[dict, CheckResult], run_hours: Optional[int] = None) ->
|
|
|
229
231
|
"up_for_hours": streak * run_hours if streak and run_hours else None,
|
|
230
232
|
"uptime_7d_percent": item.get("uptime_7d"),
|
|
231
233
|
"works_on": [name for name, ok in (item.get("sites") or {}).items() if ok],
|
|
234
|
+
"speed_kbps": item.get("speed_kbps"),
|
|
232
235
|
}
|
|
233
236
|
|
|
234
237
|
|