Skip to content
NextProxyNextProxyDocs

Extract API

Exchange an API key for a batch of passwordless ip:port entries — every parameter, response format, error code and rate limit.

The Extract API fixes the region and session configuration up front and hands back a batch of ip:port entries. Those ports are authorised by source-IP whitelist, so clients need no username or password.

GET/api/v1/proxy/extract

Authorisation requires all four

The API key goes in the query string, not a header. It belongs to a single proxy account — exactly one key per account — and its plaintext value is visible on the console's proxy account page.

Parameters

The proxy account's API key, 20–128 characters. Passed in the query string.

How many to extract, from 1 to 100.

Response format, txt or json.

Separator for txt output. Only three literal values are accepted: \n, \r\n, ,.

Note that this parameter is validated first even when type=json, so an illegal value still returns 400.

Two uppercase ISO country letters. The server enforces length 2 and characters in A-Z.

State or province name, up to 100 characters.

Compatibility behaviour: when country is empty and region is exactly 2 characters, region is treated as a country code.

City name, up to 100 characters.

Session mode, sticky or rotating.

Exit sticky session duration in minutes, from 1 to 120.

  • Required when session=sticky
  • Must be omitted when session=rotating; supplying it returns 400

Example requests

shell
curl 'https://api.example.com/api/v1/proxy/extract?apikey=YOUR_KEY&num=5&type=json&country=US&region=California&city=Los%20Angeles&session=sticky&time=10'

Rotating mode (no time):

shell
curl 'https://api.example.com/api/v1/proxy/extract?apikey=YOUR_KEY&num=10&type=txt&country=DE&session=rotating'

Response formats

txt (default)

text
1.2.3.4:20001
1.2.3.4:20002
1.2.3.4:20003

Changing the separator:

shell
# Comma-separated
curl '.../extract?apikey=KEY&num=3&format=,'
# → 1.2.3.4:20001,1.2.3.4:20002,1.2.3.4:20003

json

json
{
  "code": 0,
  "data": [
    { "ip": "1.2.3.4", "port": 20001 },
    { "ip": "1.2.3.4", "port": 20002 }
  ]
}

Using them directly

shell
# Passwordless, no credentials at all
curl -x http://1.2.3.4:20001 https://api.ipify.org

SOCKS5 works on the same port (no-auth method):

shell
curl -x socks5h://1.2.3.4:20001 https://api.ipify.org

How long the ports live

Port bindings are removed when:

  • The API key is revoked
  • The corresponding whitelist entry is deleted
  • The whitelist entry is auto-cleaned after 10 consecutive idle days
  • The gateway node serving that port becomes unhealthy — the stale binding is deleted and reassigned on the next extraction
  • The proxy account or API key record is deleted

Port ranges

Port ranges are registered by each gateway node and are not fixed constants. Registration constraints:

  • Start port ≥ 1024
  • End port ≤ 65535
  • At most 4096 ports per node

So don't hard-code a port range in firewall rules; configure from whatever the API returns.

Rate limits

120 requests per minute, counted separately for source IP and API key — exceeding either returns 429 with Retry-After: 60.

Complete error reference

StatusCodeMeaning
400invalid_proxy_extract_timetime not an integer or outside 1–120; sticky missing time; rotating supplied time
400invalid_proxy_extract_countnum not an integer or outside 1–100
400invalid_proxy_extract_typetype is neither txt nor json
400invalid_proxy_extract_formatformat is not \n / \r\n / ,
400invalid_proxy_extract_sessionsession is neither sticky nor rotating
401proxy_api_key_invalidInvalid key format or status; account/user unavailable or expired
403proxy_source_not_whitelistedSource IP not whitelisted
422proxy_api_invalidThe selected country, state, city or session option combination is unavailable
429proxy_extract_rate_limitedOver 120/min per IP or per key; includes Retry-After: 60
502client_ip_unavailableThe caller's public IPv4 could not be determined
503proxy_gateway_unavailableNo healthy gateway; binding unconfirmed; ports exhausted. Includes Retry-After: 2
500internal_errorRate-limit storage or other internal error

A usable wrapper

python
import time
from dataclasses import dataclass

import requests

API = "https://api.example.com/api/v1/proxy/extract"


@dataclass
class ExtractError(Exception):
    status: int
    code: str
    message: str


def extract(
    api_key: str,
    *,
    count: int = 10,
    country: str | None = None,
    region: str | None = None,
    city: str | None = None,
    sticky_minutes: int | None = 10,
    attempts: int = 3,
) -> list[str]:
    """Extract a batch of passwordless proxies, returning http://ip:port entries."""
    params: dict[str, object] = {
        "apikey": api_key,
        "num": count,
        "type": "json",
    }
    if country:
        params["country"] = country
    if region:
        params["region"] = region
    if city:
        params["city"] = city

    # sticky requires time; rotating must omit it
    if sticky_minutes is None:
        params["session"] = "rotating"
    else:
        params["session"] = "sticky"
        params["time"] = sticky_minutes

    for attempt in range(attempts):
        response = requests.get(API, params=params, timeout=15)

        if response.status_code == 200:
            return [
                f"http://{item['ip']}:{item['port']}"
                for item in response.json()["data"]
            ]

        # Both 429 and 503 supply Retry-After; honour it
        if response.status_code in (429, 503) and attempt < attempts - 1:
            time.sleep(int(response.headers.get("Retry-After", "2")))
            continue

        error = response.json().get("error", {})
        raise ExtractError(
            status=response.status_code,
            code=error.get("code", "unknown"),
            message=error.get("message", response.text[:200]),
        )

    raise ExtractError(status=503, code="exhausted", message="retries exhausted")


pool = extract("YOUR_API_KEY", count=5, country="US", sticky_minutes=10)
print(pool)

When not to use the Extract API

ScenarioUse instead
Egress IP changes (home broadband, containers, multi-cloud)Username options on 58971, see Quick start
Operator (ASN) targeting neededUsername options; extraction doesn't support it
A different region per requestUsername options, where region varies per request
Frequent IP changesUsername options plus new connections; don't hammer the 120/min limit

Did this page solve your problem?