Documentation

Route traffic through op.wtf.

One host, one port, every protocol. The username picks the exit and the API key is the password. Everything below builds on that.

Hostproxy.op.wtf
Port58996
Usernametype-country
Passwordyour API key

Quick start

Get started with op.wtf proxies in minutes. Follow these simple steps to integrate our proxy network into your application.

1

Create an account

Sign up for a free account and top up your balance. No credit card required to get started.

Create an account
2

Get your credentials

Find your API key in the dashboard. This will be used as your proxy password.

3

Configure your proxy

Use our simple URL format to connect through our proxy network.

Proxy URL Format
http://username:[email protected]:58996

Authentication

All requests are authenticated using your API key as the proxy password. Your username determines the proxy configuration.

Username format

Username Pattern
# Rotating
type-country

# Sticky session (residential, datacenter & mobile)
type-country-sid-session_id
ParameterDescriptionExample
sr_Optional prefix — retry blocked responses on a fresh exit (€0.001, only when it works)sr_res-us, sr_dc-de
typeProxy type for rotating: res, dc, mob, stcres, dc, mob, stc
countryTwo-letter ISO country codeus, gb, de, jp
-sid-Sticky session suffix — append to any res, dc, or mob code to pin a sessionres-us-sid-…, dc-de-sid-…
session_idSticky session identifier after -sid- — alphanumericabc123, mc_session

Endpoints & ports

ServiceHostPort
SOCKS4 / SOCKS5 / SOCKS5h / HTTP proxyproxy.op.wtf58996
API + Dashboardop.wtf443

The proxy port accepts any destination port — 80, 443, 22, 25565, anything. Outbound TCP only (no UDP relay).

Proxy types

Residential

Use res for residential IPs. Best for web scraping, social media, and bypassing geo-restrictions.

residential
res-us:[email protected]:58996

Datacenter

Use dc for fast datacenter IPs — best for high-speed requests and bulk operations, at €0.10/GB, our lowest rate. 55+ countries, many with streaming-optimized exits, and sticky sessions with -sid-. The live country list is in the dashboard proxy builder.

datacenter
# Rotating datacenter exit in the US
dc-us:[email protected]:58996

# Sticky session — same exit across requests
dc-de-sid-mysession:[email protected]:58996

Mobile

Use mob for mobile IPs. Best for social media automation and apps that require mobile IP addresses.

mobile
mob-us:[email protected]:58996

Static

Use stc for static residential IPs. Best when you need a stable long-lived IP across many sessions.

static
stc-us:[email protected]:58996

Smart Retry

Prefix any code with sr_ and a blocked response is retried on a fresh exit instead of being handed back to you. Works with any underlying code: sr_res-us, sr_dc-de, sr_res_sc-us_chicago. €0.001 per request that actually needed a retry — nothing if the first attempt worked, and nothing if none of them did.

smart retry
sr_res-us:[email protected]:58996

Countries

195+ countries. Use the two-letter ISO code in your username.

Popular codes: us gb de fr jp au ca nl es it br in. The full live list is in the dashboard proxy builder. any connects through every country at once.

City & ASN targeting

For residential proxies you can target specific cities or ASNs for precise control.

City targeting

Append the city name to the country code (use underscores for spaces).

City Targeting
res_sc-country_city:[email protected]:58996

Examples: res_sc-us_new_york, res_sc-de_berlin, res_sc-gb_london.

ASN targeting

ASN Targeting
res-us-asn-7922:[email protected]:58996

Sticky sessions

Append -sid-<session_id> to a residential, datacenter, or mobile code to keep the same exit IP across requests:

Sticky session
res-us-sid-abc123:[email protected]:58996
dc-de-sid-abc123:[email protected]:58996
mob-gb-sid-abc123:[email protected]:58996

Session IDs are alphanumeric. The session stays sticky for ~10 minutes of activity, or until the upstream IP rotates.

Smart retry

Some sites answer a proxy request with a block page or an interstitial instead of the content you asked for. Prefix any code with sr_ and we check what came back: if it's a block rather than a page, we throw it away and try again on a fresh exit.

Smart retry prefix
sr_res-us:[email protected]:58996

Works with any code

Examples
# Residential US
sr_res-us

# Datacenter Germany
sr_dc-de

# Residential, Chicago
sr_res_sc-us_chicago

# Keeps your sticky session on the first attempt
sr_res-us-sid-abc123

You only pay for requests that work. A request that succeeds first time costs nothing extra. A request that needed a retry and then got through costs €0.001. A request where no attempt got through costs you no retry fee at all — just the bandwidth.

Scope: works on http:// targets, where we can see the response. An https:// tunnel is encrypted end to end, so there is nothing for us to inspect — use the Unlocker API for those, which does the same thing and handles TLS for you.

curl
curl -x http://sr_res-us:[email protected]:58996 http://some-strict-site/

X-PR-LLS header

The HTTP proxy response carries an X-PR-LLS header containing the session ID that handled your request. Read it from the response, then reuse that ID inside a sticky-session username ({type}-{cc}-sid-<id>) on follow-up requests to keep the same exit IP.

This is the flow-based stickiness pattern: you don't have to pick a session ID up-front — let the proxy assign one, observe it, then pin to it.

terminal
curl -i -x http://res-us:[email protected]:58996 \
     https://api.ipify.org
# HTTP/1.1 200 OK
# ...
# X-PR-LLS: 8f2c1a9b
#
# Reuse the returned id to pin further requests to the same IP:
curl -x http://res-us-sid-8f2c1a9b:[email protected]:58996 \
     https://example.com

Unlocker

Send a URL, get the page back. No proxy configuration, no retry loop, no block handling on your side.

If the site answers with a block page instead of content, we discard it and try again on a fresh exit automatically. The per-request fee is charged only when we hand back real content — if nothing gets through you pay bandwidth and nothing else.

FieldDescriptionDefault
urlTarget URL — http:// or https://required
typeExit type: res, dc, mob, stcres
countryTwo-letter country codeus
city / asn / sessionFiner targeting, same meaning as in a proxy username—
methodHTTP methodGET
headersObject of request headers to forward—
bodyRequest body—
retryRetry blocked responses on a fresh exittrue
follow_redirectsFollow up to 10 redirectstrue
timeout_msPer-attempt timeout, 1000–12000030000
curl
curl -X POST https://op.wtf/api/fetch \
  -H "Authorization: Bearer op-yourkey" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/product/1","country":"de"}'
response
{
  "status": 200,
  "final_url": "https://example.com/product/1",
  "headers": { "content-type": "text/html; charset=utf-8" },
  "body": "<!doctype html>…",
  "body_base64": null,
  "bytes": 48213,
  "truncated": false,
  "ttfb_ms": 412,
  "total_ms": 690,
  "attempts": 2,
  "blocked": null,
  "exit_type": "res",
  "country": "de",
  "charged": 0.00201
}

body holds the response as text. If it isn't valid UTF-8, body is null and body_base64 carries the bytes instead. Bodies are capped at 8 MB; anything larger comes back with truncated: true.

Pricing: €0.001 per request that returns content, plus €0.001 if a retry was needed to get it, plus bandwidth at your exit type's rate. blocked non-null means no per-request fee was charged.

Geo check

Fetch one URL from many countries at once and see exactly what each of them got.

Built for anyone who has to answer "is it the same everywhere?" — ad verification, geo-pricing checks, compliance, localisation QA, SEO. One call, up to 15 countries.

curl
curl -X POST https://op.wtf/api/geo-check \
  -H "Authorization: Bearer op-yourkey" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com","countries":["us","gb","de","jp"]}'
response
{
  "url": "https://example.com",
  "exit_type": "res",
  "consistent": false,
  "checked": 4,
  "charged": 0.008,
  "results": [
    {
      "country": "us",
      "ok": true,
      "status": 200,
      "ttfb_ms": 180,
      "total_ms": 340,
      "final_url": "https://example.com/us/",
      "redirected": true,
      "title": "Example — US",
      "content_length": 20481,
      "content_hash": "9f2c…",
      "blocked": null,
      "fingerprint": ["Cloudflare"]
    }
  ]
}

content_hash is a stable fingerprint of the body, so you can compare countries without diffing pages yourself. consistent is true when every country that got through saw identical content.

Pricing: €0.002 per country checked, plus bandwidth. Duplicate country codes are removed before you're charged.

Inspect

Headers, redirect chain, edge fingerprint and a security-header audit — from any country.

curl
curl "https://op.wtf/api/inspect?url=https%3A%2F%2Fexample.com&country=gb" \
  -H "Authorization: Bearer op-yourkey"
response
{
  "url": "https://example.com",
  "final_url": "https://www.example.com/",
  "status": 200,
  "hops": 2,
  "redirects": [
    { "url": "https://example.com", "status": 301, "location": "https://www.example.com/" },
    { "url": "https://www.example.com/", "status": 200, "location": null }
  ],
  "headers": { "server": "cloudflare" },
  "fingerprint": ["Cloudflare", "Next.js"],
  "security": {
    "present": ["strict-transport-security"],
    "missing": ["content-security-policy", "x-frame-options"],
    "score": 16
  },
  "title": "Example Domain",
  "blocked": null,
  "ttfb_ms": 210,
  "total_ms": 260,
  "country": "gb",
  "charged": 0.001
}

Pricing: €0.001 per inspection plus bandwidth. A chain that never settles within 10 hops is free.

Geo DNS

Resolve a hostname as it is seen from another country.

Geo-steered DNS hands out different addresses depending on where the question comes from. This is how you check which one your users in a given market actually receive.

curl
curl "https://op.wtf/api/dns?name=example.com&type=A&country=jp" \
  -H "Authorization: Bearer op-yourkey"
response
{
  "name": "example.com",
  "type": "A",
  "country": "jp",
  "answer_count": 2,
  "answers": [
    { "name": "example.com", "type": "A", "ttl": 300, "data": "93.184.216.34" }
  ],
  "charged": 0.0002
}

Supported record types: A, AAAA, CNAME, MX, TXT, NS, SOA, SRV, HTTPS.

Pricing: €0.0002 per lookup.

Exit IP

Which address does this targeting give me right now?

Takes the same targeting parameters as a proxy username and reports the live exit. Use it to confirm a sticky session really is sticky, or to record which address handled a job.

curl
curl "https://op.wtf/api/exit-ip?type=res&country=us&session=abc123" \
  -H "Authorization: Bearer op-yourkey"
response
{
  "exit_ip": "104.28.91.7",
  "exit_type": "res",
  "country": "us",
  "session": "abc123",
  "latency_ms": 380,
  "charged": 0.0002
}

There is also GET /api/echo-ip, which needs no key and simply returns the address the request came from — point any client at it to see its own egress.

Pricing: €0.0002 per probe. A probe that doesn't come back is free.

Proxy tester

Test your own proxy list — alive, latency and real exit address for each line.

Accepts every format people actually have lying around: host:port, host:port:user:pass, user:pass@host:port and scheme://user:pass@host:port for http, https, socks4, socks5 and socks5h. Up to 200 lines per call.

curl
curl -X POST https://op.wtf/api/proxy-test \
  -H "Authorization: Bearer op-yourkey" \
  -H "Content-Type: application/json" \
  -d '{"proxies":["1.2.3.4:8080:user:pass","socks5://5.6.7.8:1080"]}'
response
{
  "tested": 2,
  "alive": 1,
  "dead": 1,
  "charged": 0.001,
  "results": [
    { "proxy": "1.2.3.4:8080", "scheme": "http", "ok": true, "alive": true,
      "status": 200, "latency_ms": 640, "exit_ip": "1.2.3.4" },
    { "proxy": "5.6.7.8:1080", "scheme": "socks5", "ok": true, "alive": false,
      "latency_ms": 10000, "error": "timeout" }
  ]
}

Credentials you submit are never echoed back — the proxy field carries host and port only.

Pricing: €0.0005 per proxy that produced a verdict. "Dead" is a verdict; a line we couldn't parse is free.

Proxy detection

Check whether an IP belongs to a known proxy or VPN pool. Pass an IP and get back the provider name(s) that operate it — or unknown when we have no record of it. Useful for scoring signups, gating abuse, or vetting your own exit IPs.

Endpoint

GET
GET https://op.wtf/api/detect?ip=<ip>

Authentication

Authenticate with your op-… API key — the same key you use for the proxy. Send it as a Bearer token, an X-Api-Key header, or a key= query parameter.

terminal
# Bearer token (recommended)
curl "https://op.wtf/api/detect?ip=1.2.3.4" \
     -H "Authorization: Bearer op-yourkey"

# X-Api-Key header
curl "https://op.wtf/api/detect?ip=1.2.3.4" \
     -H "X-Api-Key: op-yourkey"

# Query parameter
curl "https://op.wtf/api/detect?ip=1.2.3.4&key=op-yourkey"

Response

A definitive answer for an IP that is in a known proxy pool:

200 OK — known proxy
{
  "ip": "1.2.3.4",
  "status": "proxy",
  "proxy": true,
  "providers": ["Provider A", "Provider B"],
  "charged": 0.0001
}

An IP that is not in any known pool:

200 OK — clean
{
  "ip": "8.8.8.8",
  "status": "clean",
  "proxy": false,
  "providers": [],
  "charged": 0.0001
}

When we can't determine the answer, you get status: "unknown" and nothing is charged:

200 OK — unknown (free)
{
  "ip": "1.2.3.4",
  "status": "unknown",
  "proxy": false,
  "providers": [],
  "charged": 0
}
FieldDescription
statusproxy, clean, or unknown
proxytrue if the IP is in a known proxy/VPN pool
providersArray of provider names operating the IP (empty if clean/unknown)
chargedAmount debited for this check — 0.0001 or 0

Pricing

$0.0001 per check (one hundredth of a cent), billed to your credit balance — trial credits are used first. You are only charged when we return a definitive result (proxy or clean). An unknown result is always free. Private, loopback, and reserved IPs answer unknown instantly at no cost.

Errors

CodeMeaning
400 missing_ipNo ip parameter supplied.
400 invalid_ipThe ip value isn't a valid IPv4/IPv6 address.
401 invalid_api_keyNo key supplied, or the key is not recognized.
402 insufficient_balanceYour balance is too low. Top up in the dashboard.
429 rate_limitedToo many checks — slow down (120/min per key).

Bulk checks

Send up to 1000 addresses in one call instead of one request each. Duplicates are removed before billing, and the price per address is unchanged.

curl
curl -X POST https://op.wtf/api/detect/bulk \
  -H "Authorization: Bearer op-yourkey" \
  -H "Content-Type: application/json" \
  -d '{"ips":["1.2.3.4","5.6.7.8","2606:4700:4700::1111"]}'
response
{
  "checked": 2,
  "proxies": 1,
  "clean": 1,
  "charged": 0.0002,
  "results": [
    { "ip": "1.2.3.4", "status": "proxy", "proxy": true, "providers": ["ExampleVPN"] },
    { "ip": "5.6.7.8", "status": "clean", "proxy": false, "providers": [] },
    { "ip": "2606:4700:4700::1111", "status": "unknown", "proxy": false, "providers": [] }
  ]
}

checked counts only the addresses you were billed for. unknown and malformed entries are free, exactly as on the single endpoint.

Sub-keys

Scoped credentials that spend from your balance, but only as far as you allow.

Give one to each client, machine or project. Every sub-key can carry its own spend cap, bandwidth cap, expiry date and list of exits it's allowed to use. Revoke one without touching your main key or disturbing anything else.

A sub-key starts with sk- and works everywhere your main key works — as the proxy password, as a Bearer token, as X-Api-Key, or as ?key=.

FieldDescription
labelYour own name for the key
spend_limitMaximum € this key may consume. 0 = unlimited
bytes_limitMaximum bytes this key may move. 0 = unlimited
allowed_typesComma-separated exit types, e.g. res,dc. Blank = all
allowed_countriesComma-separated country codes. Blank = all
expires_atRFC 3339 timestamp after which the key stops working
activeSet false to suspend without deleting
manage sub-keys
GET    /api/keys              list your keys
POST   /api/keys              create one
PUT    /api/keys/{key}        change limits, scope or active state
POST   /api/keys/{key}/reset  zero its usage counters
DELETE /api/keys/{key}        revoke it

These are managed from your signed-in dashboard session, not with an API key — so a leaked sub-key can never mint more keys. Manage them under Keys & Access in the dashboard.

A request from a key that has used its allowance returns 402 quota_exceeded; one aimed at an exit it wasn't granted returns 403 exit_not_allowed.

IP allowlist

Authorise a whole network to use the proxy with no credentials at all.

Add an address or a CIDR range and connections from it authenticate as you — no username, no password, nothing to leak on a machine you don't fully trust. Both IPv4 and IPv6 are supported.

manage the allowlist
GET  /api/allowlist          list authorised sources
POST /api/allowlist          { "cidr": "203.0.113.0/24", "label": "office" }
POST /api/allowlist/remove   { "cidr": "203.0.113.0/24" }

Anything on this list can spend your balance. Keep the ranges as narrow as you can, and pair it with a spend limit.

Spend limits

A hard daily ceiling across everything on the account.

Set daily_spend_limit and once that much has been debited since midnight UTC, metered calls stop until the day rolls over. It covers proxy bandwidth and API calls alike — the guard rail against a runaway job quietly draining a balance overnight.

manage limits
GET /api/limits    { "daily_spend_limit": 25, "notify_below": 5, "spent_today": 3.9412 }
PUT /api/limits    { "daily_spend_limit": 25, "notify_below": 5 }

Calls refused by the cap return 402 spend_limit_reached. Set the limit back to 0 to remove it. notify_below raises a warning on your dashboard when the balance drops under that figure.

Python

proxy_example.py
import requests

proxies = {
    "http":  "socks5h://res-us:[email protected]:58996",
    "https": "socks5h://res-us:[email protected]:58996",
}
r = requests.get("https://api.ipify.org", proxies=proxies, timeout=30)
print(r.text)

Install with pip install requests[socks].

Node.js

proxy_example.mjs
import { SocksProxyAgent } from "socks-proxy-agent";
import fetch from "node-fetch";

const agent = new SocksProxyAgent(
  "socks5h://res-us:[email protected]:58996"
);
const r = await fetch("https://api.ipify.org", { agent });
console.log(await r.text());

Install with npm i socks-proxy-agent node-fetch.

cURL

terminal
# SOCKS5h
curl -x socks5h://res-us:[email protected]:58996 https://api.ipify.org

# HTTP CONNECT tunnel
curl -x http://res-us:[email protected]:58996 https://api.ipify.org

# Sticky session (canonical form generated by the dashboard)
curl -x socks5h://res-us-sid-abc123:[email protected]:58996 https://api.ipify.org

# Works on datacenter and mobile too
curl -x socks5h://dc-de-sid-abc123:[email protected]:58996 https://api.ipify.org

Browsers

Configure your browser's SOCKS5 proxy to proxy.op.wtf:58996. Username: type-country (e.g. res-us). Password: your op-… API key.

Minecraft

op.wtf routes Minecraft traffic (port 25565) through dedicated gaming upstreams optimized for low latency. The handshake is preserved and version spoofing is handled so you can join any server.

Java Edition (Proxifier)

1

Install Proxifier

Download from proxifier.com and install.

2

Add op.wtf as a SOCKS5 server

  • Server: proxy.op.wtf
  • Port: 58996
  • Protocol: SOCKS5
  • Username: res-us-sid-mc_session
  • Password: your op-… API key
3

Create a rule for javaw.exe

Add a rule matching javaw.exe and apply the op.wtf proxy. Optionally restrict it to port 25565 only.

4

Launch Minecraft

Open the launcher, start the game, connect to your target server. Your IP will appear as a residential US address.

Country & city targeting

Username variants
# Germany sticky
res-de-sid-mc_session

# Tokyo, Japan
res_sc-jp_tokyo-sid-mc_session

# Specific ISP via ASN (Comcast US)
res-us-asn-7922-sid-mc_session

Bedrock Edition

Mobile clients don't support SOCKS5 directly. Use a SOCKS5-to-HTTP bridge or a VPN client that supports SOCKS5 (such as V2Ray) to route Bedrock traffic.

Latency tips

  • Pick a country geographically close to the target server.
  • Keep the same session ID across the play session — rotating exit IPs cause lag spikes.
  • Residential adds 30–80 ms typical overhead. Datacenter (dc-us) is 5–20 ms faster but more flag-prone.

Web scraping

rotating_scraper.py
import requests
from itertools import cycle

sessions = [f"scrape_{i}" for i in range(10)]
session_iter = cycle(sessions)

def fetch(url):
    sid = next(session_iter)
    proxies = {
        "http":  f"socks5h://res-us-sid-{sid}:[email protected]:58996",
        "https": f"socks5h://res-us-sid-{sid}:[email protected]:58996",
    }
    for _ in range(3):
        try:
            return requests.get(url, proxies=proxies, timeout=20)
        except requests.RequestException:
            continue
    return None

For high throughput use aiohttp with aiohttp_socks and 50–200 concurrent requests.

Selenium / Playwright

playwright_example.py
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(proxy={
        "server":   "http://proxy.op.wtf:58996",
        "username": "res-us-sid-pw_session",
        "password": "op-yourkey",
    })
    page = browser.new_page()
    page.goto("https://api.ipify.org")
    print(page.content())

Billing

  • Pay per GB — top up by card (Visa, Mastercard, Apple Pay, Google Pay and more, from €11) or crypto (50+ coins, from €5).
  • Unlimited plans — fixed monthly rate at 1 / 10 / 100 Mbps. Bandwidth is uncharged within your speed allowance.
  • Smart Retry (sr_) — €0.001 per request that needed a retry and then got through. First-try successes and runs that never get through cost nothing extra.
  • Unlocker (/api/fetch) — €0.001 per request that returns content, plus bandwidth. Nothing when we can't get through.
  • Geo Check (/api/geo-check) — €0.002 per country checked, plus bandwidth.
  • Inspect (/api/inspect) — €0.001 per inspection, plus bandwidth.
  • Geo DNS (/api/dns) — €0.0002 per lookup.
  • Exit IP (/api/exit-ip) — €0.0002 per probe.
  • Proxy Tester (/api/proxy-test) — €0.0005 per proxy that produced a verdict.
  • Proxy Detection (/api/detect) — $0.0001 per check. Charged only for a definitive result; an unknown answer is free.
  • Trial credits — €0.20 free for connecting your Discord. Trial deducts before paid balance.
  • Referral — €0.10 each for you and a new user when they sign up with your username.

Bandwidth is metered in real-time and batched to your account every 5 seconds.

Errors

CodeMeaning
SOCKS5 0x01General failure — upstream couldn't reach target.
HTTP 407Missing or invalid API key.
HTTP 502Upstream connection failed after all retries.
SOCKS5 0x07Command not supported — UDP ASSOCIATE is unavailable.

Persistent 502s usually mean zero balance — check your dashboard.

API errors

Every API endpoint answers with {"error": "<code>"} and a matching HTTP status.

CodeHTTPMeaning
missing_api_key401No key in the header or query string.
invalid_api_key401Key not recognised.
key_disabled401That sub-key has been suspended.
key_expired401That sub-key is past its expiry date.
insufficient_balance402Account balance is too low.
quota_exceeded402That sub-key has used its allowance.
spend_limit_reached402Daily spend limit hit; resets at midnight UTC.
exit_not_allowed403That sub-key may not use the requested exit.
invalid_url · invalid_scheme400Target must be an absolute http(s) URL with a real host.
invalid_country · invalid_type · invalid_city · invalid_asn · invalid_session400Malformed targeting parameter.
too_many_countries · too_many_proxies · too_many_ips400Batch is over the per-call ceiling.
rate_limited429Too many calls this minute.
target_unreachable · timeout502The target didn't answer. Not charged.