Heardlist API
Overview
Heardlist is a free, read-only HTTP API that serves lists of public proxies: HTTP, HTTPS, SOCKS4 and SOCKS5. It merges three community-maintained sources, drops duplicates, private addresses and credentialed entries, and ranks what’s left so entries with real verification evidence come first. The data refreshes every hour.
It’s a list API. It doesn’t relay your traffic, and it doesn’t check proxies for you at request time. Read Data quality and Using proxies safely before you build on it.
Quick start
Get five verified SOCKS5 proxies as JSON:
curl "https://YOUR-HOST/v1/proxies?protocol=socks5&verified=true&limit=5"
Or as plain host:port lines, ready for a tool that reads a proxy file:
curl "https://YOUR-HOST/v1/socks5.txt?verified=true&limit=50"
Or one random station, formatted as a full proxy URL:
curl "https://YOUR-HOST/v1/random?protocol=http&format=txt&scheme=true"
Base URL & access
All endpoints live under https://YOUR-HOST/v1.
- No authentication. No API key, no signup.
- CORS is open. Responses carry
Access-Control-Allow-Origin: *, so you can call the API from a browser. - Methods.
GET,HEADandOPTIONS. Anything else returns405. - Public data only. Don’t use the list to attack or abuse other people’s services.
Responses
List endpoints return a JSON envelope by default. The example below uses documentation-range addresses, not real proxies.
{
"meta": {
"count": 2,
"total": 118,
"limit": 2,
"offset": 0,
"sort": "quality",
"updated_at": "2026-10-07T10:07:04.112Z"
},
"data": [
{
"proxy": "203.0.113.10:1080",
"url": "socks5://203.0.113.10:1080",
"protocol": "socks5",
"host": "203.0.113.10",
"port": 1080,
"country": "US",
"anonymity": null,
"latency": 0.18,
"source": "monosans",
"verified": true
},
{
"proxy": "198.51.100.7:8080",
"url": "http://198.51.100.7:8080",
"protocol": "http",
"host": "198.51.100.7",
"port": 8080,
"country": "DE",
"anonymity": null,
"latency": 2.55,
"source": "monosans",
"verified": true
}
]
}
| Field | Type | Meaning |
|---|---|---|
proxy | string | host:port. |
url | string | Proxy URL to hand to a client. The scheme describes how you talk to the proxy. https entries are plain HTTP proxies that tunnel TLS, so their URL starts with http://. |
protocol | string | http, https, socks4 or socks5. |
host, port | string, integer | IPv4 address and port. |
country | string | null | ISO 3166-1 alpha-2 code, when the source provides one. |
anonymity | string | null | elite, anonymous or transparent. Only some sources state it; otherwise null. |
latency | number | null | Response time in seconds measured by the upstream checker at its last run. null when the source doesn’t measure it. |
source | string | monosans, proxifly or thespeedx. |
verified | boolean | true when the source verifies every entry it publishes. Heardlist itself does not re-check. |
List responses also set X-Total-Count (matches before paging) and X-Updated-At (when the data was last refreshed) as headers, which is handy with format=txt and format=csv.
Errors
Errors are JSON with a stable code and a human-readable message.
{ "error": { "code": "invalid_param", "message": "Invalid protocol: ftp. Allowed: http, https, socks4, socks5." } }
| Status | Code | When |
|---|---|---|
| 400 | invalid_param | A query parameter has a bad value. The message names it. |
| 404 | not_found | No such endpoint. |
| 405 | method_not_allowed | Anything other than GET, HEAD or OPTIONS. |
| 429 | rate_limited | Too many requests. Wait for the Retry-After seconds. |
| 500 | internal_error | Something broke on our side. Retry shortly. |
An empty result is not an error: filters that match nothing return 200 with "data": [].
Limits & caching
- Rate limit. By default, 120 requests per minute per IP. The operator of a deployment can change it.
- Page size.
limitis 1–5000, default 100. Page withoffset. - Refresh cadence. Data is rebuilt hourly. Polling more often than every few minutes gains nothing.
- Caching. Responses are cached for one minute in browsers and five minutes at the edge.
/v1/randomandsort=randomare never cached. - Staleness. If every upstream is unreachable, the last good data keeps being served. After 12 hours without a successful refresh it expires and the list becomes empty rather than serve very old addresses.
/v1/healthreports this.
GET /v1/proxies
The main list endpoint. Combine any of these filters; they’re ANDed together. Comma-separated values within one filter are ORed.
| Parameter | Default | Description |
|---|---|---|
protocol | any | http, https, socks4, socks5. Comma-separate to combine, e.g. socks4,socks5. |
country | any | ISO alpha-2 codes, case-insensitive: US,DE. Entries with no known country never match. |
anonymity | any | elite, anonymous, transparent. Entries where the source doesn’t state it never match. |
source | any | monosans, proxifly, thespeedx. |
verified | any | true keeps only entries from sources that verify what they publish. false keeps the rest. |
max_latency | none | Seconds, above 0 up to 120. Keeps entries with a measured response time at or under this value. Entries with no measurement are excluded. |
sort | quality | quality: source tier, then response time, then anonymity. latency: fastest measured first, unmeasured entries excluded. random: a fresh random draw each call. |
limit | 100 | 1–5000. |
offset | 0 | Entries to skip. Ignored when sort=random. |
format | json | json, txt (one host:port per line) or csv (columns host,port,protocol,country,anonymity,latency,source,verified). |
scheme | false | With format=txt, prefix each line with the proxy URL scheme: socks5://203.0.113.10:1080. |
Example: the 20 fastest verified HTTP proxies in Germany or France.
curl "https://YOUR-HOST/v1/proxies?protocol=http&country=DE,FR&verified=true&sort=latency&limit=20"
GET /v1/random
Shorthand for /v1/proxies?sort=random&limit=1. It accepts every filter above, and limit to draw several at once. Responses are never cached, so each call is a fresh draw. Use it for a quick rotation, and run your own check on whatever you get.
curl "https://YOUR-HOST/v1/random?protocol=socks5&verified=true"
GET /v1/{protocol}.txt
Plain-text lists for tools that load a proxy file. {protocol} is http, https, socks4 or socks5. It takes the same filters and paging as /v1/proxies, and always returns text/plain.
curl -o socks5.txt "https://YOUR-HOST/v1/socks5.txt?verified=true&limit=500"
GET /v1/stats
Counts and freshness for the current dataset. Counts are after de-duplication across sources.
{
"total": 9024,
"verified": 1435,
"countries": 71,
"by_protocol": { "http": 3100, "https": 980, "socks4": 640, "socks5": 4304 },
"by_source": { "monosans": 1435, "proxifly": 5200, "thespeedx": 2389 },
"updated_at": "2026-10-07T10:07:04.112Z",
"age_minutes": 12,
"stale": false,
"sources": {
"monosans": { "ok": true, "fetched_at": "2026-10-07T10:07:04.112Z", "count": 1435 }
}
}
The numbers are illustrative. stale turns true after three hours without a refresh. A source that failed its last run shows "ok": false with an error string, and its previous entries stay in the list until they expire.
GET /v1/sources
The upstream sources, their tier, whether they verify entries, their homepage and license, and the status of the last refresh. Use it to credit the data you rely on.
GET /v1/health
A cheap liveness check for monitors. It returns 200 when there is any data and 503 when the list is empty. In the body, ok is true only when the list is non-empty and fresher than three hours.
{ "ok": true, "total": 9024, "updated_at": "2026-10-07T10:07:04.112Z", "stale": false }
Protocols & anonymity
| Protocol | What it is | Pick it for |
|---|---|---|
http | Application-layer proxy. For plain HTTP it can read and rewrite headers and bodies. For HTTPS it tunnels with the CONNECT method, which clients do automatically. | General web requests. |
https | HTTP proxies a source explicitly flags as handling HTTPS. You still connect to the proxy over plain HTTP; the label is about what it can tunnel. | When you need a source’s own HTTPS flag. |
socks4 | Relays raw TCP. No UDP, no authentication, no remote DNS. | Legacy TCP tools. |
socks5 | Relays TCP and UDP, supports authentication and remote DNS, so hostnames resolve on the proxy and don’t leak from your machine. | Most scraping and anything that isn’t only web traffic. |
Entries from the verified tier labelled http are CONNECT-capable HTTP proxies, so they can carry HTTPS even though there is no separate https file for that source.
Anonymity is judged from the headers a target server sees. Elite proxies add nothing that identifies you or the proxy. Anonymous proxies hide your IP but announce themselves, for example with a Via header. Transparent proxies pass your real IP along in X-Forwarded-For and give no privacy at all. SOCKS proxies can’t add HTTP headers, so checkers tend to rate them elite. A checker that only tests over HTTPS will also rate a leaky HTTP proxy elite, because the tunnel hides its headers. Treat the anonymity field as a hint.
Data quality
Heardlist merges three upstream lists and orders them by tier:
- monosans/proxy-list (
verified: true). Re-checked hourly with a full real-page fetch; proxies that connect and then stall are excluded. Provides response time and country. MIT licensed. - proxifly/free-proxy-list. A large raw pool with anonymity and country fields. We don’t verify it. In the combined file reviewed on 7 Oct 2026, 50,855 of 51,262 entries were labelled
transparent, and itsscorewas 1 for every entry, so we ignore it. - TheSpeedX/PROXY-List. Daily
host:portfiles with no metadata and no verification evidence.
When the same protocol + host:port appears in more than one source, the highest tier wins. Private, loopback, link-local and carrier-grade-NAT addresses, invalid ports and entries that carry credentials are dropped. At most 10,000 entries per protocol are kept from any one source, which truncates proxifly’s very large SOCKS5 file.
“Verified” means the source’s check passed at its last run. Heardlist does not re-check, and a free proxy’s status decays within hours. In a research probe on 7 Oct 2026, 25 HTTP proxies from the verified tier were tried through a real request minutes after the hourly re-check: 9 answered correctly (36%), with response times from 0.75 s to 16.2 s and a median of 6.3 s. That is the best case. Expect fewer to work later in the hour, and fewer still from the unverified tiers.
So: always put a checker you control between the list and your workload. There’s one in the examples.
Using proxies safely
Free public proxies are untrusted by construction. Whoever runs one can see and change whatever isn’t protected end to end, and some are run as honeypots or are compromised machines.
- Never send credentials, tokens, session cookies, payment data or private API keys through one. Public data only.
- Don’t send plain HTTP. The operator can read it, log it and inject scripts into the response.
- Keep TLS certificate verification on. A tunnel keeps the payload encrypted, but a hostile proxy can still refuse, downgrade or tamper with the handshake. The hostname you connect to is also visible to the operator, unless you use Encrypted Client Hello.
- Use short timeouts. Three seconds or less for connect and read, so a stalling proxy can’t hold your workers.
- Rotate and expect blocks. Many target sites block datacenter ranges and known proxy lists.
- Isolate the workload. Run checkers and scrapers in a stateless container with no access to your internal network.
If you need reliability or privacy, a paid provider with an authenticated endpoint is the right tool. A free list is the right tool for large volumes of public, non-sensitive requests.
Code examples
Fetch, check, then use (Python)
Pull a candidate set, keep only the proxies that complete a real HTTPS request inside three seconds, and use those. This needs aiohttp and aiohttp-socks.
import asyncio
import aiohttp
from aiohttp_socks import ProxyConnector
API = "https://YOUR-HOST/v1/proxies?verified=true&limit=200"
TEST_URL = "https://example.com/"
async def alive(proxy_url: str) -> bool:
try:
connector = ProxyConnector.from_url(proxy_url) # http://, socks4://, socks5://
timeout = aiohttp.ClientTimeout(total=3)
async with aiohttp.ClientSession(connector=connector, timeout=timeout) as s:
async with s.get(TEST_URL) as r:
return r.status == 200
except Exception:
return False
async def main():
async with aiohttp.ClientSession() as s:
async with s.get(API) as r:
candidates = [p["url"] for p in (await r.json())["data"]]
results = await asyncio.gather(*(alive(u) for u in candidates))
good = [u for u, ok in zip(candidates, results) if ok]
print(f"{len(good)} of {len(candidates)} passed")
for u in good[:10]:
print(u)
asyncio.run(main())
Fetch and test an HTTP proxy (Node.js)
Node 18+ with undici installed.
import { ProxyAgent, fetch } from "undici";
const API = "https://YOUR-HOST/v1/proxies?protocol=http&verified=true&limit=20";
const { data } = await (await fetch(API)).json();
for (const p of data) {
try {
const res = await fetch("https://example.com/", {
dispatcher: new ProxyAgent(p.url),
signal: AbortSignal.timeout(3000),
});
console.log(res.status, p.proxy);
} catch {
// dead, slow or hostile: skip it
}
}
Load a text list in the browser
CORS is open, so the API works from a web page. Here it feeds a country filter into a list.
const res = await fetch("https://YOUR-HOST/v1/proxies?country=IN&limit=10");
if (!res.ok) throw new Error((await res.json()).error.message);
const { meta, data } = await res.json();
console.log(`${meta.count} of ${meta.total}`, data.map((p) => p.proxy));