proxy-scraper-cli 1.20.0__tar.gz → 1.22.0__tar.gz

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