FREEPROXY JOURNAL · ARTICLE

Proxy List API in Python: A Safe Quickstart

FreeProxy Editorial · Published · Reviewed

A reliable Python proxy-list client fetches a small snapshot, checks protocol and expiry fields, retries only transient failures, and rotates after a real request failure. Keep the API key server-side, use a short timeout, and remember that a verified public endpoint is not a private relay or a guarantee for every target.

Boundary: this article describes collection and verification of public proxy data; it does not guarantee that any proxy works for a particular target or override the target site's and network's rules.

Direct answer

A Python client should treat a proxy list API as a short-lived data source. Fetch only the records you need, preserve the protocol and expiry metadata, use bounded retries with backoff, and rotate after a real request failure. Store the API key outside source code and keep proxy traffic limited to authorized, low-risk work.

Who this is for and what it does not promise

This quickstart is for developers building a small test harness, data-quality job, or controlled automation that needs current public proxy records. It does not turn a public endpoint into a private or anonymous connection, and it does not promise access to a particular target. Do not send credentials, payment data, session tokens, or production secrets through public proxies.

Why use an API instead of scraping a proxy-list page?

HTML pages are presentation formats. A list API gives a stable response contract, explicit protocol fields, timestamps, and machine-readable errors. That lets a client decide whether a record is fresh before opening a connection and lets it cache a representation without copying a changing page layout.

FreeProxy exposes GET /api/v1/proxies for a filtered snapshot and GET /api/v1/proxy for one matching record. The API returns metadata and connection records; it does not fetch the target page for the caller or act as an open forward-proxy endpoint.

1. Fetch a small snapshot with Python's standard library

Set FREEPROXY_API_KEY in the server environment. The key stays in a request header and never appears in the URL or source repository.

import json
import os
import urllib.parse
import urllib.request

base_url = "https://proxylistapi.xyz/api/v1/proxies"
query = urllib.parse.urlencode({"protocol": "http", "limit": 20})
request = urllib.request.Request(
    f"{base_url}?{query}",
    headers={"X-API-Key": os.environ["FREEPROXY_API_KEY"]},
)

with urllib.request.urlopen(request, timeout=15) as response:
    snapshot = json.load(response)

for record in snapshot.get("proxies", []):
    print(record["protocol"], record["proxy"], record["expires_at"])

The endpoint can return an empty proxies array with a successful response. Treat that as an empty snapshot, not as permission to remove all safety checks or loop without a delay.

2. Filter by expiry and retain the evidence

A list response can change while your job is running. Parse expires_at before selecting a record, and keep validated_at and validation_latency_ms with the record so your logs explain why it was selected. The validation latency is an observation about the check; it is not a download-speed promise for your target.

from datetime import datetime, timezone

now = datetime.now(timezone.utc)
usable = []
for record in snapshot.get("proxies", []):
    expires_at = datetime.fromisoformat(record["expires_at"].replace("Z", "+00:00"))
    if expires_at > now:
        usable.append(record)

Keep the selection policy explicit. For a short diagnostic job, choose one record and stop after a small number of failures. For a longer job, maintain a bounded queue and remove a record after a real timeout, connection error, or target rejection.

3. Configure the proxy in the HTTP client

Fetching a record and using it are separate operations. A list API response does not automatically configure urllib or Requests. For Requests, the proxy URL belongs in the client configuration:

import requests

proxy_url = "http://HOST:PORT"  # use a record returned by the API
proxies = {"http": proxy_url, "https": proxy_url}
response = requests.get(
    "https://example.com/health-check",
    proxies=proxies,
    timeout=10,
)
response.raise_for_status()

Use a URL and target that you control or are authorized to test. Never assume that https in the destination URL makes an unknown proxy trustworthy. Keep sensitive requests on a direct, controlled connection unless you have evaluated the intermediary.

4. Handle errors without creating a retry storm

Build error handling around the response contract:

Response Recommended action
200 with records Filter by protocol and expires_at, then select a bounded candidate.
200 with count: 0 Remove a filter or wait for the next snapshot; do not spin.
304 Reuse the cached representation and re-check each record's expiry.
401 Check the key and active subscription state.
404 from /api/v1/proxy No matching record; retry later with a delay.
429 Honor Retry-After, then use exponential backoff with jitter.
5xx Treat as temporary, cap attempts, and preserve the last good snapshot.

The API key and the client IP have separate rate limits. Request a small page and use the ETag header for polling rather than downloading the same representation on every loop.

5. Poll with ETags

Save the response ETag for the exact filter set. On the next request, send If-None-Match:

headers = {
    "X-API-Key": os.environ["FREEPROXY_API_KEY"],
    "If-None-Match": cached_etag,
}
request = urllib.request.Request(
    "https://proxylistapi.xyz/api/v1/proxies?protocol=http&limit=20",
    headers=headers,
)

A 304 tells you that the representation is unchanged. It does not extend a record beyond expires_at, so keep expiry checks in the caller. Cache only the last successful snapshot and replace it atomically after a fresh 200 response.

Key-management rules

  • Read the key from a server-side environment variable or secret manager.
  • Do not put it in query parameters, Git history, screenshots, or client-side JavaScript.
  • Redact authorization headers and proxy credentials from logs.
  • Rotate the key if it may have been exposed.
  • Keep the test target and legal authorization documented for the job.

Next step

For the meaning and limits of a “verified” record, read how to evaluate a free proxy list. If the workflow needs stronger ownership, privacy, or uptime commitments, compare the decision factors in free versus paid proxies.

Sources and evidence

← Back to the Journal