proxy-scraper-cli 1.23.0__tar.gz → 1.24.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.
Files changed (131) hide show
  1. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/PKG-INFO +61 -10
  2. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/README.md +60 -9
  3. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxy_scraper_cli.egg-info/PKG-INFO +61 -10
  4. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxy_scraper_cli.egg-info/SOURCES.txt +1 -0
  5. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/__init__.py +1 -1
  6. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/api.py +1 -1
  7. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/app.py +99 -6
  8. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/cli.py +1 -1
  9. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/pages.py +2 -2
  10. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/parsing.py +5 -4
  11. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/site/index.html +3 -3
  12. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/sites.py +3 -0
  13. proxy_scraper_cli-1.24.0/tests/test_recheck_stdin.py +263 -0
  14. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_sites.py +22 -5
  15. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/LICENSE +0 -0
  16. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxy_scraper_cli.egg-info/dependency_links.txt +0 -0
  17. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxy_scraper_cli.egg-info/entry_points.txt +0 -0
  18. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxy_scraper_cli.egg-info/requires.txt +0 -0
  19. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxy_scraper_cli.egg-info/top_level.txt +0 -0
  20. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/__main__.py +0 -0
  21. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/action.py +0 -0
  22. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/agent.py +0 -0
  23. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/asndb.py +0 -0
  24. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/blocklist.py +0 -0
  25. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/charts.py +0 -0
  26. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/checker.py +0 -0
  27. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/compat.py +0 -0
  28. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/completion.py +0 -0
  29. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/exporters.py +0 -0
  30. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/fetchcache.py +0 -0
  31. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/geo.py +0 -0
  32. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/geodb.py +0 -0
  33. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/handshake.py +0 -0
  34. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/history.py +0 -0
  35. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/judges.py +0 -0
  36. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/mcp_entry.py +0 -0
  37. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/mcp_server.py +0 -0
  38. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/mirror.py +0 -0
  39. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/netio.py +0 -0
  40. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/options.py +0 -0
  41. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/output.py +0 -0
  42. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/paths.py +0 -0
  43. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/pipeline.py +0 -0
  44. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/preferences.py +0 -0
  45. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/proxypages.py +0 -0
  46. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/publish.py +0 -0
  47. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/ranking.py +0 -0
  48. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/report.py +0 -0
  49. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/runsteps.py +0 -0
  50. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/server/__init__.py +0 -0
  51. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/server/api.py +0 -0
  52. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/server/core.py +0 -0
  53. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/server/dashboard.html +0 -0
  54. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/server/http.py +0 -0
  55. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/server/pool.py +0 -0
  56. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/server/socks.py +0 -0
  57. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/server/status.py +0 -0
  58. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/server/upstream.py +0 -0
  59. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/site/apple-touch-icon.png +0 -0
  60. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/site/googleaac1161b7853c5b5.html +0 -0
  61. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/site/logo.png +0 -0
  62. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/site/og.png +0 -0
  63. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/sources.json +0 -0
  64. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/sources.py +0 -0
  65. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/speed.py +0 -0
  66. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/targets.py +0 -0
  67. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/ui/__init__.py +0 -0
  68. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/ui/dashboard.py +0 -0
  69. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/ui/keys.py +0 -0
  70. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/ui/report.py +0 -0
  71. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/ui/serve.py +0 -0
  72. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/ui/widgets.py +0 -0
  73. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/proxyscraper/ui/wizard.py +0 -0
  74. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/pyproject.toml +0 -0
  75. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/setup.cfg +0 -0
  76. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_action.py +0 -0
  77. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_agent.py +0 -0
  78. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_api.py +0 -0
  79. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_app.py +0 -0
  80. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_asndb.py +0 -0
  81. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_auth.py +0 -0
  82. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_blocklist.py +0 -0
  83. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_charts.py +0 -0
  84. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_checker.py +0 -0
  85. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_compat.py +0 -0
  86. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_completion.py +0 -0
  87. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_discovery_growth.py +0 -0
  88. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_exporters.py +0 -0
  89. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_fetchcache.py +0 -0
  90. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_geodb.py +0 -0
  91. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_judges.py +0 -0
  92. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_learning.py +0 -0
  93. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_live_api.py +0 -0
  94. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_mcp_server.py +0 -0
  95. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_mine_sources.py +0 -0
  96. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_mirror.py +0 -0
  97. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_options.py +0 -0
  98. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_output_stdout.py +0 -0
  99. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_own_sources.py +0 -0
  100. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_pac.py +0 -0
  101. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_packaging.py +0 -0
  102. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_pages.py +0 -0
  103. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_parsing.py +0 -0
  104. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_parsing_fuzz.py +0 -0
  105. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_paths.py +0 -0
  106. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_pick.py +0 -0
  107. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_pipeline.py +0 -0
  108. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_preferences.py +0 -0
  109. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_proxy_pages.py +0 -0
  110. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_proxy_sources.py +0 -0
  111. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_publish.py +0 -0
  112. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_report.py +0 -0
  113. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_robustness.py +0 -0
  114. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_rotator.py +0 -0
  115. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_serve_api.py +0 -0
  116. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_serve_dashboard.py +0 -0
  117. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_serve_password.py +0 -0
  118. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_serve_refill.py +0 -0
  119. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_serve_v2.py +0 -0
  120. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_server.py +0 -0
  121. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_server_closed_writer.py +0 -0
  122. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_server_fixes.py +0 -0
  123. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_sources_json.py +0 -0
  124. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_speed.py +0 -0
  125. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_speed_ranking.py +0 -0
  126. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_survival_ranking.py +0 -0
  127. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_tamper.py +0 -0
  128. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_targets.py +0 -0
  129. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_ui.py +0 -0
  130. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.0}/tests/test_uptime.py +0 -0
  131. {proxy_scraper_cli-1.23.0 → proxy_scraper_cli-1.24.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.23.0
3
+ Version: 1.24.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
@@ -75,16 +75,23 @@ Most free proxy lists are 95 % dead, and a good part of the rest are honeypots o
75
75
 
76
76
  **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)
77
77
 
78
- <picture>
79
- <source media="(prefers-color-scheme: dark)" srcset="docs/checks-dark.svg">
80
- <source media="(prefers-color-scheme: light)" srcset="docs/checks-light.svg">
81
- <img src="docs/checks-dark.svg" alt="The five checks: 700+ lists, a real handshake, two sites with one IP, nothing injected, the details" width="100%">
82
- </picture>
78
+ **Try it – no install, about five seconds:**
79
+
80
+ ```bash
81
+ uvx proxy-scraper-cli --pick 5 --types socks5 # 5 checked proxies
82
+
83
+ # or just the plain list
84
+ curl -s https://maximilianfeix.github.io/proxy-scraper/socks5.txt | head
85
+ ```
86
+
87
+ `uvx` comes with [uv](https://docs.astral.sh/uv/); `pipx run proxy-scraper-cli --pick 5` does the same.
83
88
 
84
89
  <div align="center">
85
- <img src="docs/demo.svg" alt="Animated demo: setup wizard, collecting, live dashboard and final report" width="880">
90
+ <img src="docs/demo.svg" alt="Animated demo: the live dashboard during a check, the report, the setup wizard and collecting" width="880">
86
91
  </div>
87
92
 
93
+ > **Who runs free proxies – and is it safe to use them?** Mostly nobody on purpose: misconfigured servers with an open port, a few deliberately open ones, infected machines, and traps that log or rewrite your traffic. That's why every proxy here has to pass [five checks](#how-it-works), and why they're for public data and testing – never for logins, payments or anything personal. [More on where they come from →](#who-runs-free-proxies)
94
+
88
95
  <details>
89
96
  <summary><b>Table of contents</b></summary>
90
97
 
@@ -222,7 +229,7 @@ Every protocol and country also has its own page with a plain download, e.g. [SO
222
229
  | 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) |
223
230
  | HTTPS-capable only | `type://ip:port` | [https.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/https.txt) |
224
231
  | Elite only | `type://ip:port` | [elite.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/elite.txt) |
225
- | 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) |
232
+ | Gets through to Google · Reddit · Amazon · Instagram · TikTok · Discord (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) · [discord.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/discord.txt) |
226
233
  | 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) |
227
234
  | 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) |
228
235
 
@@ -460,7 +467,7 @@ pool = itertools.cycle(p.url for p in proxies)
460
467
  r = requests.get("https://api.ipify.org", proxies={"https": next(pool)}, timeout=15) # pip install "requests[socks]"
461
468
  ```
462
469
 
463
- 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`.
470
+ Same filters as `find_proxies`, plus `min_uptime`, `works_on` (`["google"]`, `"reddit"`, `"amazon"`, `"instagram"`, `"tiktok"`, `"discord"`) and `limit`. Every result also has `uptime_24h`, `uptime_7d`, `first_seen`, `up_for_hours` and `sites`.
464
471
 
465
472
  Or let the library do the retrying: `ProxyRotator` loads a URL through the list and moves on to the next proxy when one fails – HTTPS only through proxies with verified TLS.
466
473
 
@@ -583,6 +590,13 @@ The live list can also come to you: [`bot/`](bot/) is a Discord bot that posts e
583
590
 
584
591
  ## How it works
585
592
 
593
+ <picture>
594
+ <source media="(prefers-color-scheme: dark)" srcset="docs/checks-dark.svg">
595
+ <source media="(prefers-color-scheme: light)" srcset="docs/checks-light.svg">
596
+ <img src="docs/checks-dark.svg" alt="The five checks: 700+ lists, a real handshake, two sites with one IP, nothing injected, the details" width="100%">
597
+ </picture>
598
+
599
+
586
600
  ```mermaid
587
601
  flowchart LR
588
602
  A[sources.json<br/>meta lists<br/>GitHub discovery] --> B[Fetch & parse<br/>in parallel on all cores]
@@ -777,6 +791,14 @@ Username wishes – `country-us` sends everything out through US proxies, `sessi
777
791
  proxy-scraper --recheck live --want 20 -y -o - | grep '^socks5://' > socks.txt
778
792
  ```
779
793
 
794
+ **Check a list you already have** – `--recheck -` reads it from stdin: plain `ip:port` lines, `type://ip:port`, logins, JSON, a CSV export or a table pasted from a website (HTML or Markdown), in the order it came in. Only what works from your network comes out:
795
+
796
+ ```bash
797
+ curl -s https://example.com/proxies.txt | proxy-scraper --recheck - -o - > working.txt
798
+ ```
799
+
800
+ Proxies without a type are tried as HTTP and as SOCKS5 – or as SOCKS4 with `--types socks4` alone. A password with a comma, quote, `|` or bracket can't be told apart from the text around it in a paste; put such proxies in a file, one per line, and use `--recheck file.txt`.
801
+
780
802
  **Any tool, through the rotating server**
781
803
 
782
804
  ```bash
@@ -849,7 +871,7 @@ curl.exe -x (Get-Content "$run\all.txt" -TotalCount 1) http://api.ipify.org
849
871
  | `--no-blocklisted` | skip proxies whose exit IP is on the SpamCop blocklist – those often get captchas |
850
872
  | `--no-dnsbl` | skip the blocklist lookup |
851
873
  | `--target URL` | only proxies that reach this site (repeatable) |
852
- | `--recheck [FILE\|live]` | only check proxies from a file, the last run, or the public live list |
874
+ | `--recheck [FILE\|-\|live]` | only check proxies from a file, stdin (`-`), the last run, or the public live list |
853
875
  | `--fast` | skip the HTTPS test (confirmation and anonymity still run) |
854
876
  | `--no-geo` | skip the country lookup |
855
877
  | `-c`, `--concurrency N` | simultaneous checks (default: 2000) |
@@ -896,6 +918,25 @@ The repo does part of the work itself:
896
918
 
897
919
  ## FAQ
898
920
 
921
+ <a id="who-runs-free-proxies"></a>
922
+
923
+ <details open>
924
+ <summary><b>Who runs free proxies – and should you use them?</b></summary>
925
+ <br>
926
+
927
+ Almost nobody runs a free proxy for you. What ends up on public lists is usually one of these:
928
+
929
+ - **Misconfigured servers** – a Squid, a router or an app with a proxy port that was meant to stay internal.
930
+ - **Deliberately open proxies** – a few volunteers and research projects, and services that give some away to sell the rest.
931
+ - **Infected machines** – computers and IoT devices whose owners don't know they relay traffic. Many residential exits are like this.
932
+ - **Traps** – honeypots that log what goes through them, and proxies that rewrite pages to inject ads or scripts.
933
+
934
+ proxy-scraper can't tell an infected home router from an open office proxy, but it filters what it can measure: a proxy has to answer two independent requests with the same exit IP (honeypots that only answer scanners drop out), deliver a known page byte for byte (injectors drop out), and HTTPS counts only with a certificate that verifies end to end. Each hit says whether its exit is in a datacenter.
935
+
936
+ Good uses: public data, checking how a site looks from another country, testing your own blocking and rate limits, research. Never send passwords, cookies, payment or personal data through a free proxy, and keep HTTPS certificate checks on. Use them only where you're allowed to.
937
+
938
+ </details>
939
+
899
940
  <details>
900
941
  <summary><b>Almost nothing gets through.</b></summary>
901
942
  <br>
@@ -950,6 +991,8 @@ Only for things that don't matter. Public proxies are run by strangers who can r
950
991
 
951
992
  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.
952
993
 
994
+ Shipped in v1.24: `--recheck -` for lists you pipe in, which proxies get through to Discord, and a README you can try in five seconds.
995
+
953
996
  Shipped in v1.22 and v1.23: a live dashboard for the rotating server, `--export pac` and an hourly `proxy.pac`, "best first" that counts how likely a proxy is still up, the lists in a repository of their own ([free-proxy-list](https://github.com/maximilianfeix/free-proxy-list)), daily snapshots on Hugging Face, `brew install`, a Chinese README, Python 3.14, and a recipe for Burp Suite, ZAP and mitmproxy.
954
997
 
955
998
  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.
@@ -1020,6 +1063,14 @@ proxyscraper/
1020
1063
 
1021
1064
  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.
1022
1065
 
1066
+ Thanks to everyone who helped build it – new sources, countries, Python 3.14, examples and more:
1067
+
1068
+ <a href="https://github.com/maximilianfeix/proxy-scraper/graphs/contributors">
1069
+ <img src="https://contrib.rocks/image?repo=maximilianfeix/proxy-scraper" alt="Contributors to proxy-scraper">
1070
+ </a>
1071
+
1072
+ Want to join? [Beginner-friendly issues](../../issues?q=is%3Aopen+label%3A%22good+first+issue%22) say where to start.
1073
+
1023
1074
  <a href="https://star-history.com/#maximilianfeix/proxy-scraper&Date">
1024
1075
  <picture>
1025
1076
  <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=maximilianfeix/proxy-scraper&type=Date&theme=dark">
@@ -33,16 +33,23 @@ Most free proxy lists are 95 % dead, and a good part of the rest are honeypots o
33
33
 
34
34
  **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)
35
35
 
36
- <picture>
37
- <source media="(prefers-color-scheme: dark)" srcset="docs/checks-dark.svg">
38
- <source media="(prefers-color-scheme: light)" srcset="docs/checks-light.svg">
39
- <img src="docs/checks-dark.svg" alt="The five checks: 700+ lists, a real handshake, two sites with one IP, nothing injected, the details" width="100%">
40
- </picture>
36
+ **Try it – no install, about five seconds:**
37
+
38
+ ```bash
39
+ uvx proxy-scraper-cli --pick 5 --types socks5 # 5 checked proxies
40
+
41
+ # or just the plain list
42
+ curl -s https://maximilianfeix.github.io/proxy-scraper/socks5.txt | head
43
+ ```
44
+
45
+ `uvx` comes with [uv](https://docs.astral.sh/uv/); `pipx run proxy-scraper-cli --pick 5` does the same.
41
46
 
42
47
  <div align="center">
43
- <img src="docs/demo.svg" alt="Animated demo: setup wizard, collecting, live dashboard and final report" width="880">
48
+ <img src="docs/demo.svg" alt="Animated demo: the live dashboard during a check, the report, the setup wizard and collecting" width="880">
44
49
  </div>
45
50
 
51
+ > **Who runs free proxies – and is it safe to use them?** Mostly nobody on purpose: misconfigured servers with an open port, a few deliberately open ones, infected machines, and traps that log or rewrite your traffic. That's why every proxy here has to pass [five checks](#how-it-works), and why they're for public data and testing – never for logins, payments or anything personal. [More on where they come from →](#who-runs-free-proxies)
52
+
46
53
  <details>
47
54
  <summary><b>Table of contents</b></summary>
48
55
 
@@ -180,7 +187,7 @@ Every protocol and country also has its own page with a plain download, e.g. [SO
180
187
  | 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) |
181
188
  | HTTPS-capable only | `type://ip:port` | [https.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/https.txt) |
182
189
  | Elite only | `type://ip:port` | [elite.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/elite.txt) |
183
- | 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) |
190
+ | Gets through to Google · Reddit · Amazon · Instagram · TikTok · Discord (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) · [discord.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/discord.txt) |
184
191
  | 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) |
185
192
  | 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) |
186
193
 
@@ -418,7 +425,7 @@ pool = itertools.cycle(p.url for p in proxies)
418
425
  r = requests.get("https://api.ipify.org", proxies={"https": next(pool)}, timeout=15) # pip install "requests[socks]"
419
426
  ```
420
427
 
421
- 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`.
428
+ Same filters as `find_proxies`, plus `min_uptime`, `works_on` (`["google"]`, `"reddit"`, `"amazon"`, `"instagram"`, `"tiktok"`, `"discord"`) and `limit`. Every result also has `uptime_24h`, `uptime_7d`, `first_seen`, `up_for_hours` and `sites`.
422
429
 
423
430
  Or let the library do the retrying: `ProxyRotator` loads a URL through the list and moves on to the next proxy when one fails – HTTPS only through proxies with verified TLS.
424
431
 
@@ -541,6 +548,13 @@ The live list can also come to you: [`bot/`](bot/) is a Discord bot that posts e
541
548
 
542
549
  ## How it works
543
550
 
551
+ <picture>
552
+ <source media="(prefers-color-scheme: dark)" srcset="docs/checks-dark.svg">
553
+ <source media="(prefers-color-scheme: light)" srcset="docs/checks-light.svg">
554
+ <img src="docs/checks-dark.svg" alt="The five checks: 700+ lists, a real handshake, two sites with one IP, nothing injected, the details" width="100%">
555
+ </picture>
556
+
557
+
544
558
  ```mermaid
545
559
  flowchart LR
546
560
  A[sources.json<br/>meta lists<br/>GitHub discovery] --> B[Fetch & parse<br/>in parallel on all cores]
@@ -735,6 +749,14 @@ Username wishes – `country-us` sends everything out through US proxies, `sessi
735
749
  proxy-scraper --recheck live --want 20 -y -o - | grep '^socks5://' > socks.txt
736
750
  ```
737
751
 
752
+ **Check a list you already have** – `--recheck -` reads it from stdin: plain `ip:port` lines, `type://ip:port`, logins, JSON, a CSV export or a table pasted from a website (HTML or Markdown), in the order it came in. Only what works from your network comes out:
753
+
754
+ ```bash
755
+ curl -s https://example.com/proxies.txt | proxy-scraper --recheck - -o - > working.txt
756
+ ```
757
+
758
+ Proxies without a type are tried as HTTP and as SOCKS5 – or as SOCKS4 with `--types socks4` alone. A password with a comma, quote, `|` or bracket can't be told apart from the text around it in a paste; put such proxies in a file, one per line, and use `--recheck file.txt`.
759
+
738
760
  **Any tool, through the rotating server**
739
761
 
740
762
  ```bash
@@ -807,7 +829,7 @@ curl.exe -x (Get-Content "$run\all.txt" -TotalCount 1) http://api.ipify.org
807
829
  | `--no-blocklisted` | skip proxies whose exit IP is on the SpamCop blocklist – those often get captchas |
808
830
  | `--no-dnsbl` | skip the blocklist lookup |
809
831
  | `--target URL` | only proxies that reach this site (repeatable) |
810
- | `--recheck [FILE\|live]` | only check proxies from a file, the last run, or the public live list |
832
+ | `--recheck [FILE\|-\|live]` | only check proxies from a file, stdin (`-`), the last run, or the public live list |
811
833
  | `--fast` | skip the HTTPS test (confirmation and anonymity still run) |
812
834
  | `--no-geo` | skip the country lookup |
813
835
  | `-c`, `--concurrency N` | simultaneous checks (default: 2000) |
@@ -854,6 +876,25 @@ The repo does part of the work itself:
854
876
 
855
877
  ## FAQ
856
878
 
879
+ <a id="who-runs-free-proxies"></a>
880
+
881
+ <details open>
882
+ <summary><b>Who runs free proxies – and should you use them?</b></summary>
883
+ <br>
884
+
885
+ Almost nobody runs a free proxy for you. What ends up on public lists is usually one of these:
886
+
887
+ - **Misconfigured servers** – a Squid, a router or an app with a proxy port that was meant to stay internal.
888
+ - **Deliberately open proxies** – a few volunteers and research projects, and services that give some away to sell the rest.
889
+ - **Infected machines** – computers and IoT devices whose owners don't know they relay traffic. Many residential exits are like this.
890
+ - **Traps** – honeypots that log what goes through them, and proxies that rewrite pages to inject ads or scripts.
891
+
892
+ proxy-scraper can't tell an infected home router from an open office proxy, but it filters what it can measure: a proxy has to answer two independent requests with the same exit IP (honeypots that only answer scanners drop out), deliver a known page byte for byte (injectors drop out), and HTTPS counts only with a certificate that verifies end to end. Each hit says whether its exit is in a datacenter.
893
+
894
+ Good uses: public data, checking how a site looks from another country, testing your own blocking and rate limits, research. Never send passwords, cookies, payment or personal data through a free proxy, and keep HTTPS certificate checks on. Use them only where you're allowed to.
895
+
896
+ </details>
897
+
857
898
  <details>
858
899
  <summary><b>Almost nothing gets through.</b></summary>
859
900
  <br>
@@ -908,6 +949,8 @@ Only for things that don't matter. Public proxies are run by strangers who can r
908
949
 
909
950
  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.
910
951
 
952
+ Shipped in v1.24: `--recheck -` for lists you pipe in, which proxies get through to Discord, and a README you can try in five seconds.
953
+
911
954
  Shipped in v1.22 and v1.23: a live dashboard for the rotating server, `--export pac` and an hourly `proxy.pac`, "best first" that counts how likely a proxy is still up, the lists in a repository of their own ([free-proxy-list](https://github.com/maximilianfeix/free-proxy-list)), daily snapshots on Hugging Face, `brew install`, a Chinese README, Python 3.14, and a recipe for Burp Suite, ZAP and mitmproxy.
912
955
 
913
956
  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.
@@ -978,6 +1021,14 @@ proxyscraper/
978
1021
 
979
1022
  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.
980
1023
 
1024
+ Thanks to everyone who helped build it – new sources, countries, Python 3.14, examples and more:
1025
+
1026
+ <a href="https://github.com/maximilianfeix/proxy-scraper/graphs/contributors">
1027
+ <img src="https://contrib.rocks/image?repo=maximilianfeix/proxy-scraper" alt="Contributors to proxy-scraper">
1028
+ </a>
1029
+
1030
+ Want to join? [Beginner-friendly issues](../../issues?q=is%3Aopen+label%3A%22good+first+issue%22) say where to start.
1031
+
981
1032
  <a href="https://star-history.com/#maximilianfeix/proxy-scraper&Date">
982
1033
  <picture>
983
1034
  <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=maximilianfeix/proxy-scraper&type=Date&theme=dark">
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: proxy-scraper-cli
3
- Version: 1.23.0
3
+ Version: 1.24.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
@@ -75,16 +75,23 @@ Most free proxy lists are 95 % dead, and a good part of the rest are honeypots o
75
75
 
76
76
  **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)
77
77
 
78
- <picture>
79
- <source media="(prefers-color-scheme: dark)" srcset="docs/checks-dark.svg">
80
- <source media="(prefers-color-scheme: light)" srcset="docs/checks-light.svg">
81
- <img src="docs/checks-dark.svg" alt="The five checks: 700+ lists, a real handshake, two sites with one IP, nothing injected, the details" width="100%">
82
- </picture>
78
+ **Try it – no install, about five seconds:**
79
+
80
+ ```bash
81
+ uvx proxy-scraper-cli --pick 5 --types socks5 # 5 checked proxies
82
+
83
+ # or just the plain list
84
+ curl -s https://maximilianfeix.github.io/proxy-scraper/socks5.txt | head
85
+ ```
86
+
87
+ `uvx` comes with [uv](https://docs.astral.sh/uv/); `pipx run proxy-scraper-cli --pick 5` does the same.
83
88
 
84
89
  <div align="center">
85
- <img src="docs/demo.svg" alt="Animated demo: setup wizard, collecting, live dashboard and final report" width="880">
90
+ <img src="docs/demo.svg" alt="Animated demo: the live dashboard during a check, the report, the setup wizard and collecting" width="880">
86
91
  </div>
87
92
 
93
+ > **Who runs free proxies – and is it safe to use them?** Mostly nobody on purpose: misconfigured servers with an open port, a few deliberately open ones, infected machines, and traps that log or rewrite your traffic. That's why every proxy here has to pass [five checks](#how-it-works), and why they're for public data and testing – never for logins, payments or anything personal. [More on where they come from →](#who-runs-free-proxies)
94
+
88
95
  <details>
89
96
  <summary><b>Table of contents</b></summary>
90
97
 
@@ -222,7 +229,7 @@ Every protocol and country also has its own page with a plain download, e.g. [SO
222
229
  | 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) |
223
230
  | HTTPS-capable only | `type://ip:port` | [https.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/https.txt) |
224
231
  | Elite only | `type://ip:port` | [elite.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/elite.txt) |
225
- | 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) |
232
+ | Gets through to Google · Reddit · Amazon · Instagram · TikTok · Discord (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) · [discord.txt](https://raw.githubusercontent.com/maximilianfeix/proxy-scraper/proxy-list/works-with/discord.txt) |
226
233
  | 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) |
227
234
  | 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) |
228
235
 
@@ -460,7 +467,7 @@ pool = itertools.cycle(p.url for p in proxies)
460
467
  r = requests.get("https://api.ipify.org", proxies={"https": next(pool)}, timeout=15) # pip install "requests[socks]"
461
468
  ```
462
469
 
463
- 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`.
470
+ Same filters as `find_proxies`, plus `min_uptime`, `works_on` (`["google"]`, `"reddit"`, `"amazon"`, `"instagram"`, `"tiktok"`, `"discord"`) and `limit`. Every result also has `uptime_24h`, `uptime_7d`, `first_seen`, `up_for_hours` and `sites`.
464
471
 
465
472
  Or let the library do the retrying: `ProxyRotator` loads a URL through the list and moves on to the next proxy when one fails – HTTPS only through proxies with verified TLS.
466
473
 
@@ -583,6 +590,13 @@ The live list can also come to you: [`bot/`](bot/) is a Discord bot that posts e
583
590
 
584
591
  ## How it works
585
592
 
593
+ <picture>
594
+ <source media="(prefers-color-scheme: dark)" srcset="docs/checks-dark.svg">
595
+ <source media="(prefers-color-scheme: light)" srcset="docs/checks-light.svg">
596
+ <img src="docs/checks-dark.svg" alt="The five checks: 700+ lists, a real handshake, two sites with one IP, nothing injected, the details" width="100%">
597
+ </picture>
598
+
599
+
586
600
  ```mermaid
587
601
  flowchart LR
588
602
  A[sources.json<br/>meta lists<br/>GitHub discovery] --> B[Fetch & parse<br/>in parallel on all cores]
@@ -777,6 +791,14 @@ Username wishes – `country-us` sends everything out through US proxies, `sessi
777
791
  proxy-scraper --recheck live --want 20 -y -o - | grep '^socks5://' > socks.txt
778
792
  ```
779
793
 
794
+ **Check a list you already have** – `--recheck -` reads it from stdin: plain `ip:port` lines, `type://ip:port`, logins, JSON, a CSV export or a table pasted from a website (HTML or Markdown), in the order it came in. Only what works from your network comes out:
795
+
796
+ ```bash
797
+ curl -s https://example.com/proxies.txt | proxy-scraper --recheck - -o - > working.txt
798
+ ```
799
+
800
+ Proxies without a type are tried as HTTP and as SOCKS5 – or as SOCKS4 with `--types socks4` alone. A password with a comma, quote, `|` or bracket can't be told apart from the text around it in a paste; put such proxies in a file, one per line, and use `--recheck file.txt`.
801
+
780
802
  **Any tool, through the rotating server**
781
803
 
782
804
  ```bash
@@ -849,7 +871,7 @@ curl.exe -x (Get-Content "$run\all.txt" -TotalCount 1) http://api.ipify.org
849
871
  | `--no-blocklisted` | skip proxies whose exit IP is on the SpamCop blocklist – those often get captchas |
850
872
  | `--no-dnsbl` | skip the blocklist lookup |
851
873
  | `--target URL` | only proxies that reach this site (repeatable) |
852
- | `--recheck [FILE\|live]` | only check proxies from a file, the last run, or the public live list |
874
+ | `--recheck [FILE\|-\|live]` | only check proxies from a file, stdin (`-`), the last run, or the public live list |
853
875
  | `--fast` | skip the HTTPS test (confirmation and anonymity still run) |
854
876
  | `--no-geo` | skip the country lookup |
855
877
  | `-c`, `--concurrency N` | simultaneous checks (default: 2000) |
@@ -896,6 +918,25 @@ The repo does part of the work itself:
896
918
 
897
919
  ## FAQ
898
920
 
921
+ <a id="who-runs-free-proxies"></a>
922
+
923
+ <details open>
924
+ <summary><b>Who runs free proxies – and should you use them?</b></summary>
925
+ <br>
926
+
927
+ Almost nobody runs a free proxy for you. What ends up on public lists is usually one of these:
928
+
929
+ - **Misconfigured servers** – a Squid, a router or an app with a proxy port that was meant to stay internal.
930
+ - **Deliberately open proxies** – a few volunteers and research projects, and services that give some away to sell the rest.
931
+ - **Infected machines** – computers and IoT devices whose owners don't know they relay traffic. Many residential exits are like this.
932
+ - **Traps** – honeypots that log what goes through them, and proxies that rewrite pages to inject ads or scripts.
933
+
934
+ proxy-scraper can't tell an infected home router from an open office proxy, but it filters what it can measure: a proxy has to answer two independent requests with the same exit IP (honeypots that only answer scanners drop out), deliver a known page byte for byte (injectors drop out), and HTTPS counts only with a certificate that verifies end to end. Each hit says whether its exit is in a datacenter.
935
+
936
+ Good uses: public data, checking how a site looks from another country, testing your own blocking and rate limits, research. Never send passwords, cookies, payment or personal data through a free proxy, and keep HTTPS certificate checks on. Use them only where you're allowed to.
937
+
938
+ </details>
939
+
899
940
  <details>
900
941
  <summary><b>Almost nothing gets through.</b></summary>
901
942
  <br>
@@ -950,6 +991,8 @@ Only for things that don't matter. Public proxies are run by strangers who can r
950
991
 
951
992
  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.
952
993
 
994
+ Shipped in v1.24: `--recheck -` for lists you pipe in, which proxies get through to Discord, and a README you can try in five seconds.
995
+
953
996
  Shipped in v1.22 and v1.23: a live dashboard for the rotating server, `--export pac` and an hourly `proxy.pac`, "best first" that counts how likely a proxy is still up, the lists in a repository of their own ([free-proxy-list](https://github.com/maximilianfeix/free-proxy-list)), daily snapshots on Hugging Face, `brew install`, a Chinese README, Python 3.14, and a recipe for Burp Suite, ZAP and mitmproxy.
954
997
 
955
998
  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.
@@ -1020,6 +1063,14 @@ proxyscraper/
1020
1063
 
1021
1064
  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.
1022
1065
 
1066
+ Thanks to everyone who helped build it – new sources, countries, Python 3.14, examples and more:
1067
+
1068
+ <a href="https://github.com/maximilianfeix/proxy-scraper/graphs/contributors">
1069
+ <img src="https://contrib.rocks/image?repo=maximilianfeix/proxy-scraper" alt="Contributors to proxy-scraper">
1070
+ </a>
1071
+
1072
+ Want to join? [Beginner-friendly issues](../../issues?q=is%3Aopen+label%3A%22good+first+issue%22) say where to start.
1073
+
1023
1074
  <a href="https://star-history.com/#maximilianfeix/proxy-scraper&Date">
1024
1075
  <picture>
1025
1076
  <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=maximilianfeix/proxy-scraper&type=Date&theme=dark">
@@ -105,6 +105,7 @@ tests/test_preferences.py
105
105
  tests/test_proxy_pages.py
106
106
  tests/test_proxy_sources.py
107
107
  tests/test_publish.py
108
+ tests/test_recheck_stdin.py
108
109
  tests/test_report.py
109
110
  tests/test_robustness.py
110
111
  tests/test_rotator.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.23.0"
4
+ __version__ = "1.24.0"
5
5
 
6
6
 
7
7
  def __getattr__(name):
@@ -215,7 +215,7 @@ async def live_proxies_async(*, types: Iterable[str] = PROXY_TYPES, countries: I
215
215
  Same filters as find_proxies, plus
216
216
  min_uptime only proxies listed in at least this share (percent) of the week's runs, e.g. 90
217
217
  works_on only proxies that got through to these sites in the last run: google, reddit, amazon, instagram,
218
- tiktok
218
+ tiktok, discord
219
219
  min_speed only proxies that downloaded at least this many KiB/s in the last run
220
220
  limit at most this many (0 = all)
221
221
  """
@@ -5,6 +5,7 @@ from __future__ import annotations
5
5
  import asyncio
6
6
  import contextlib
7
7
  import ipaddress
8
+ import re
8
9
  import socket
9
10
  import sys
10
11
  import tempfile
@@ -12,7 +13,7 @@ import time
12
13
  from collections import Counter
13
14
  from dataclasses import replace
14
15
  from pathlib import Path
15
- from typing import List, Optional, Tuple
16
+ from typing import Dict, List, Optional, Tuple
16
17
 
17
18
  from rich.live import Live
18
19
  from rich.text import Text
@@ -42,7 +43,17 @@ from .netio import INSECURE_HOSTS, http_get
42
43
  from .options import STDOUT, RunOptions
43
44
  from .output import ResultWriter, latest_results
44
45
  from .pages import REPO_URL
45
- from .parsing import PROXY_TYPES, parse_keys, split_key
46
+ from .parsing import (
47
+ JSON_IP_PORT_RE,
48
+ JSON_PORT_IP_RE,
49
+ PROXY_RE,
50
+ PROXY_TYPES,
51
+ TYPE_ALIASES,
52
+ parse_blob,
53
+ parse_keys,
54
+ parse_proxy_line,
55
+ split_key,
56
+ )
46
57
  from .paths import is_checkout
47
58
  from .pipeline import (
48
59
  CheckRun,
@@ -114,9 +125,90 @@ async def confirm_target() -> Optional[str]:
114
125
  return ip if await probe_confirm_target(ip, timeout=8) else None
115
126
 
116
127
 
128
+ STDIN = "-" # --recheck -: the candidates come from a pipe
129
+
130
+
131
+ def read_stdin() -> bytes:
132
+ """What was piped in, as bytes – a stray non-UTF-8 byte in a pasted table mustn't sink the whole list.
133
+ A terminal on stdin means nothing was piped: reading it would just wait."""
134
+ if sys.stdin is None or sys.stdin.isatty():
135
+ raise OSError(0, "nothing was piped in (try: cat proxies.txt | proxy-scraper --recheck -)")
136
+ buffer = getattr(sys.stdin, "buffer", None)
137
+ data = buffer.read() if buffer is not None else sys.stdin.read().encode("utf-8", "replace")
138
+ return data[3:] if data.startswith(b"\xef\xbb\xbf") else data # the BOM Notepad and PowerShell write
139
+
140
+
141
+ # a typed proxy anywhere in a word – at its start, or after "url":" in compact JSON; it ends at a quote, comma or
142
+ # bracket, which a password could in theory contain but practically never does
143
+ _TYPED_PROXY = re.compile(
144
+ rb"(?<![A-Za-z0-9])(?:" + b"|".join(s.encode() for s in TYPE_ALIASES if TYPE_ALIASES[s] != "auto")
145
+ + rb")://[^\s\"'`,;()\[\]{}<>]+", re.IGNORECASE)
146
+ # what separates an untyped proxy from the text around it: spaces, but also the quotes, commas, pipes and
147
+ # brackets of compact JSON, a CSV row or a Markdown table – otherwise '"proxy":"user:pass@ip:port' would read
148
+ # as a login of '"proxy":"user'
149
+ _WORD_SPLIT = re.compile(rb"[\s\"'`,;|()\[\]{}<>]+")
150
+ # what a proxy user name is made of; anything else in front of "@" ("proxy=user", "US|user") is text glued on,
151
+ # and the address is then checked without a login rather than with a made-up one
152
+ _LOGIN_USER = re.compile(r"[A-Za-z0-9._~+%-]+")
153
+
154
+
155
+ # IP and port in neighbouring columns of a CSV export or a Markdown table: "8.8.4.4,8080" / "| 8.8.4.4 | 8080 |"
156
+ _COLUMN_PAIR = re.compile(rb"(?<![\d.])(\d{1,3}(?:\.\d{1,3}){3})\s*[,;|]\s*(\d{2,5})(?![\d.])")
157
+
158
+
159
+ def _address_positions(data: bytes) -> Dict[str, int]:
160
+ """Where each ip:port first appears, in any layout the extraction reads: ip:port, "ip port", a table cell
161
+ pair, JSON in either order – so a list keeps its order whatever it looks like."""
162
+ hits = [(m.start(), m.group(1), m.group(2))
163
+ for regex in (PROXY_RE, JSON_IP_PORT_RE, _COLUMN_PAIR) for m in regex.finditer(data)]
164
+ hits += [(m.start(), m.group(2), m.group(1)) for m in JSON_PORT_IP_RE.finditer(data)]
165
+ first: Dict[str, int] = {}
166
+ for at, ip, port in sorted(hits):
167
+ first.setdefault(f"{'.'.join(str(int(p)) for p in ip.split(b'.'))}:{int(port)}", at)
168
+ return first
169
+
170
+
171
+ def stdin_keys(data: bytes, types) -> List[str]:
172
+ """Every proxy in the piped text, in the order it came in (lists often come best first, and --limit takes
173
+ the first jobs).
174
+
175
+ Every type://… in the text is read as a proxy on its own – at the start of a line, after other text,
176
+ several on a line, inside JSON – which also keeps a login whose password has '@' or '/'. Untyped proxies –
177
+ a bare word like user:pass@ip:port (read whole, so the login stays), or ip/port inside JSON or a table –
178
+ are tried as HTTP and right after as SOCKS5, or as the types asked for when neither of those is (a list of
179
+ SOCKS4 proxies piped in with --types socks4). Not the "auto" mode of sources: its "plain lines only count
180
+ as the majority" rule is for scraped lists, and whoever pipes a list in means all of it."""
181
+ wanted = tuple(types)
182
+ bare_types = tuple(t for t in ("http", "socks5") if t in wanted) or wanted
183
+
184
+ def address(key: str) -> str:
185
+ return split_key(key)[1].rpartition("@")[2]
186
+
187
+ typed = {k for k in (parse_proxy_line(m.group(0).decode("utf-8", "replace"), None)
188
+ for m in _TYPED_PROXY.finditer(data)) if k}
189
+ words = [w.decode("utf-8", "replace") for w in _WORD_SPLIT.split(data) if w and b"://" not in w]
190
+ words = [w for w in words if "@" not in w or _LOGIN_USER.fullmatch(w.rpartition("@")[0].partition(":")[0])]
191
+ whole_words = {k for w in words for t in bare_types for k in [parse_proxy_line(w, t)] if k}
192
+ # full: sources pick the "ip port"/table regex from their first 8 KB, a paste may be a.txt then b.html
193
+ found = {k for t in bare_types for k in parse_blob(data, t, wanted, full=True).split("\n") if k}
194
+ columns = [f"{m.group(1).decode()}:{m.group(2).decode()}" for m in _COLUMN_PAIR.finditer(data)]
195
+ found |= {k for pair in columns for t in bare_types for k in [parse_proxy_line(pair, t)] if k}
196
+ # an address read with its login (or with a type of its own) owns it: the regex's login-less copy, or a
197
+ # bare copy of a typed proxy of an unwanted type, mustn't come back. Claimed before the type filter.
198
+ claimed = {address(k) for k in typed} | {address(k) for k in whole_words if "@" in split_key(k)[1]}
199
+ keys = ({k for k in typed | whole_words if split_key(k)[0] in wanted}
200
+ | {k for k in found if address(k) not in claimed})
201
+
202
+ first = _address_positions(data)
203
+ rank = {t: i for i, t in enumerate(PROXY_TYPES)} # http before socks4 before socks5 for the same address
204
+ return sorted(keys, key=lambda k: (first.get(address(k), len(data)), rank.get(split_key(k)[0], 9), k))
205
+
206
+
117
207
  def load_recheck_jobs(target: str, types, history: ProxyHistory) -> List[str]:
118
- """--recheck: a file, otherwise the last run plus history."""
119
- if target:
208
+ """--recheck: a file, '-' for stdin, otherwise the last run plus history."""
209
+ if target == STDIN:
210
+ return stdin_keys(read_stdin(), types)
211
+ elif target:
120
212
  lines = Path(target).expanduser().read_text(encoding="utf-8").splitlines()
121
213
  # lines without type:// in files like http.txt take the type from the file name
122
214
  default = next((t for t in PROXY_TYPES if t in Path(target).name.lower()), None)
@@ -311,9 +403,10 @@ class Run:
311
403
  jobs = load_recheck_jobs(opts.recheck, opts.types, self.history)
312
404
  except (OSError, UnicodeDecodeError) as e:
313
405
  reason = e.strerror if isinstance(e, OSError) and e.strerror else "not a text file"
314
- note(f"Can't read {opts.recheck}: {reason}.", BAD, "✘")
406
+ note(f"Can't read {'stdin' if opts.recheck == STDIN else opts.recheck}: {reason}.", BAD, "✘")
315
407
  return []
316
- info("Recheck", f"{fmt(len(jobs))} proxies from {opts.recheck or 'the last run + history'}")
408
+ where = "stdin" if opts.recheck == STDIN else opts.recheck or "the last run + history"
409
+ info("Recheck", f"{fmt(len(jobs))} proxies from {where}")
317
410
  else:
318
411
  jobs = await self._scrape_jobs()
319
412
 
@@ -183,7 +183,7 @@ def parse_args(argv: Optional[List[str]] = None) -> argparse.Namespace:
183
183
  g.add_argument("--no-dnsbl", action="store_true",
184
184
  help="don't look up whether exit IPs are on the SpamCop blocklist")
185
185
  g.add_argument("--recheck", nargs="?", const="", metavar="FILE",
186
- help="only check proxies from FILE – without FILE: last run + history; "
186
+ help="only check proxies from FILE ('-' reads them from stdin) – without FILE: last run + history; "
187
187
  "'live': the live list from GitHub (seconds instead of minutes, e.g. with --serve)")
188
188
 
189
189
  f = p.add_argument_group("Filters (for the result files)")