If you've ever grabbed a "free proxy list" and pointed your scraper at it, you know what happens next: timeouts, connection resets, and the odd proxy that returns a captcha page instead of the site you asked for.
That's not bad luck. Most free proxies are short-lived. A list that was correct an hour ago is mostly dead now, and a lot of lists only check whether a port is open, which says very little about whether a real HTTPS request will go through.
This post shows a small Python setup that deals with that, in three steps:
- Pull a fresh list.
- Re-test it yourself with a real HTTPS request.
- Rotate through the survivors and retry on failure.
At the end there's a shortcut if you don't want to manage the list at all.
Disclosure: I run SolProxy, the free list used in the examples. The code works with any list that returns
ip:portlines.
What makes a free list worth using
Many free lists are copies of other free lists, checked every few minutes to every half hour, and few of them say how they check. When we built the SolProxy list we set a stricter bar:
- Re-tested every minute with a real HTTPS request, not a port check. Anything that fails is dropped right away.
- TLS tampering is filtered out. Proxies that swap the certificate (and could read your traffic) never make it onto the list.
- Uptime you can see. Each proxy shows how many of its last 10 checks it passed, so you can pick stable ones instead of guessing.
- More than an IP and port. Every row has the real exit IP, ISP, type, latency and speed.
- One endpoint that skips the dead ones for you. With a free account it only picks proxies that passed at least 9 of their last 10 checks. More on that at the end.
Here's how that compares with some popular free lists, based on what each one says on its own page (October 2026):
| SolProxy | free-proxy-list.net | Proxifly | Geonode | |
|---|---|---|---|---|
| How often checked | Every minute | Every 10 to 30 min | Every 5 min | Every minute |
| Check method published | Real HTTPS request | Not stated | Not stated | Not stated |
| Filters TLS tampering | Yes | Not stated | Not stated | Not stated |
| Uptime shown | Yes (last 10 checks) | No | No | Yes |
| Exit IP and ISP shown | Yes | No | No | ASN only |
| Latency shown | Yes | No | No | Yes |
| Free rotating endpoint | Yes (free account) | No (paid) | No (npm module) | No (paid) |
| SOCKS4/5 | No | Paid only | Yes | Yes |
If you need SOCKS, the others are the better pick today. If you want HTTPS proxies that were confirmed working a minute ago, or one address that handles the rotation for you, that's where SolProxy is different.
In a small test from a home fiber connection, the endpoint answered 20 out of 20 requests, with a median latency around 1.5 s and no Google captchas. That's a small sample, so take it as a direction, not a benchmark.
1. Pull a fresh list
The list has a plain-text API you can filter by country and type:
import requests
LIST_URL = "https://solproxy.net/free-proxy-list/api.txt"
def get_proxies(country=None):
params = {"country": country} if country else {}
text = requests.get(LIST_URL, params=params, timeout=15).text
return [line.strip() for line in text.splitlines() if line.strip()]
proxies = get_proxies("US")
print(len(proxies), "proxies")
Any other list that gives you ip:port lines works the same way.
2. Re-test before you trust it
Even a list checked a minute ago can contain proxies that died since. Test them yourself, in parallel, with the kind of request you'll actually make:
import concurrent.futures as cf
TEST_URL = "https://api.ipify.org"
def works(proxy, timeout=8):
url = f"http://{proxy}"
try:
r = requests.get(TEST_URL, proxies={"http": url, "https": url}, timeout=timeout)
return r.ok and r.text.strip() != ""
except requests.RequestException:
return False
def alive(proxies, workers=50):
with cf.ThreadPoolExecutor(workers) as ex:
results = ex.map(works, proxies)
return [p for p, ok in zip(proxies, results) if ok]
pool = alive(proxies)
print(len(pool), "passed")
Two things worth knowing:
-
Test over HTTPS, not HTTP. Plenty of proxies pass plain HTTP and fail on
CONNECT. -
Keep certificate verification on.
requestsverifies TLS by default. If a proxy only "works" withverify=False, it is swapping the certificate and can read your traffic. Throw it away.
3. Rotate and retry
Free proxies die mid-job, so every request needs a fallback:
import random
def fetch(url, pool, tries=5):
for _ in range(tries):
proxy = random.choice(pool)
p = f"http://{proxy}"
try:
r = requests.get(url, proxies={"http": p, "https": p}, timeout=10)
if r.status_code < 400:
return r
except requests.RequestException:
pass
pool.remove(proxy) # drop dead ones as you go
if not pool:
break
raise RuntimeError("no working proxy left")
r = fetch("https://example.com", pool)
print(r.status_code)
Re-run step 2 every few minutes if your job is long.
The shortcut: one endpoint, no list
If you don't want to manage any of this, SolProxy also has a single free endpoint. It picks a live proxy for each request, only from the ones that passed at least 9 of their last 10 checks, and retries if one dies. The list itself stays open to everyone; the endpoint needs a free account (25 GB a month). Register, copy your token from the dashboard and put it where the password goes:
curl -x http://free:YOUR_TOKEN@ws.solproxy.net:8501 https://api.ipify.org
In Python:
p = "http://free:YOUR_TOKEN@ws.solproxy.net:8501"
r = requests.get("https://api.ipify.org", proxies={"http": p, "https": p}, timeout=15)
print(r.text) # a different IP than yours
Honest limits
- These are public free proxies, and most are datacenter IPs. They're fine for small jobs, testing and geo checks.
- Sites with serious bot protection (Amazon, for example) block nearly all of them. Free proxies won't change that.
- Never send logins, cookies or anything private through a free proxy.
If something's broken or you'd like a filter that isn't there, leave a comment. I read them all.
Top comments (0)