Find the right proxy
Filter live inventory by location, connection type, and plan.
Build with the PreProx Marketplace API for static proxy leases with unlimited bandwidth. Discover shared or private plans, purchase a 24-hour lease, and manage renewals.
curl --fail-with-body "https://preprox.com/api/v1/marketplace/account" \
-H "Authorization: Bearer $PREPROX_API_KEY" \
-H 'Accept: application/json'Purchase and manage shared or private marketplace leases. GB data packages, SMS verification and rental numbers are separate products and are outside this API.
Unlimited proxy bandwidth during the lease, subject to acceptable use. API request limits still apply. API key expiry does not extend a lease.
The Marketplace API brings inventory discovery, quotes, checkout, and management of 24-hour static proxy leases into your own server-side application. Leases include unlimited proxy bandwidth during their active period, subject to acceptable use. Every key belongs to a PreProx account and can access only that account’s wallet and leases.
https://preprox.com/api/v1/marketplaceFilter live inventory by location, connection type, and plan.
Set a price ceiling and pay from your existing wallet.
Read connections, refresh leases, and manage renewal.
GB residential data packages, SMS verification, rental numbers, payments, and account administration are outside this API. Mobile and Wi-Fi marketplace networks depend on live inventory. Add wallet funds through your PreProx dashboard.
Sign in, verify your email, then create an API key in your dashboard. Choose the minimum permissions your integration needs. The full key is shown once; save it in a server environment variable or secret manager.
An API key can last 1, 3, 6 or 12 months, or until revoked with Never. This controls API access only. Each proxy lease has its own 24-hour duration; enabled auto-renew authorizes a new billable lease period.
Authorization: Bearer YOUR_PREPROX_API_KEY
Accept: application/json
Content-Type: application/jsonContent-Type is required when sending a JSON body.Account, wallet, inventory, and owned lease details.
Create quotes, purchase, refresh, update renewal or IP access, and request eligible refunds.
Use keys only on your server. Keep them out of browser code, mobile bundles, public repositories, and logs. Expiry and revocation apply to the next request. Your account must remain verified and enabled.
Check your wallet, discover an available plan, create a quote, then confirm the purchase. Quotes last five minutes and do not reserve inventory. Treat px_ and q_ IDs as opaque, case-sensitive strings.
# cURL · review your price ceiling before purchasing.
export PREPROX_API_BASE='https://preprox.com/api/v1/marketplace'
export PREPROX_API_KEY='YOUR_PREPROX_API_KEY'
# 1. Check the wallet that will pay for this lease.
curl --fail-with-body "$PREPROX_API_BASE/account" \
-H "Authorization: Bearer $PREPROX_API_KEY" \
-H 'Accept: application/json'
# 2. Discover inventory and copy one available shared plan's px_ ID.
curl --fail-with-body --get "$PREPROX_API_BASE/proxies" \
-H "Authorization: Bearer $PREPROX_API_KEY" \
-H 'Accept: application/json' \
--data-urlencode 'country=US' --data-urlencode 'plan=shared'
# 3. Replace the placeholder with that complete inventory ID.
curl --fail-with-body "$PREPROX_API_BASE/quotes" \
-H "Authorization: Bearer $PREPROX_API_KEY" \
-H 'Accept: application/json' -H 'Content-Type: application/json' \
-d '{"proxy_id":"px_YOUR_INVENTORY_ID","plan":"shared"}'
# 4. This call PURCHASES a lease. Review the quote before sending.
# Replace the q_ ID. Persist a unique key and this exact body first.
# Retry the SAME body and key if this request times out.
curl --fail-with-body "$PREPROX_API_BASE/leases" \
-H "Authorization: Bearer $PREPROX_API_KEY" \
-H 'Accept: application/json' -H 'Content-Type: application/json' \
-H 'Idempotency-Key: order-YOUR_UNIQUE_ORDER_ID' \
-d '{"quote_id":"q_YOUR_QUOTE_ID","max_price":"0.42"}'# Python 3 · standard library · purchases ONE lease up to USD 0.42.
# Set PREPROX_API_BASE and PREPROX_API_KEY in your environment first.
import json
import os
import uuid
from decimal import Decimal
from urllib.error import HTTPError
from urllib.request import Request, urlopen
BASE = os.environ["PREPROX_API_BASE"].rstrip("/")
KEY = os.environ["PREPROX_API_KEY"]
MAX_PRICE = "0.42" # Review this ceiling before running.
def api(method, path, body=None, purchase_key=None):
headers = {"Authorization": f"Bearer {KEY}", "Accept": "application/json"}
data = None if body is None else json.dumps(body).encode("utf-8")
if data is not None:
headers["Content-Type"] = "application/json"
if purchase_key:
headers["Idempotency-Key"] = purchase_key
try:
request = Request(BASE + path, data=data, headers=headers, method=method)
with urlopen(request, timeout=30) as response:
return json.load(response)
except HTTPError as error:
raise RuntimeError(f"HTTP {error.code}: {json.load(error)}") from error
account = api("GET", "/account")["data"]
if Decimal(account["wallet_balance"]) < Decimal(MAX_PRICE):
raise SystemExit("Fund your PreProx wallet first.")
inventory = api("GET", "/proxies?country=US&plan=shared")
proxy = next((p for p in inventory["data"]
if p["plans"]["shared"]["available"]
and Decimal(p["plans"]["shared"]["amount"]) <= Decimal(MAX_PRICE)), None)
if proxy is None:
raise SystemExit("No match on this page; check meta.next_cursor or adjust filters.")
quote = api("POST", "/quotes", {"proxy_id": proxy["id"], "plan": "shared"})["data"]
purchase_key = str(uuid.uuid4())
purchase_body = {"quote_id": quote["id"], "max_price": MAX_PRICE}
# PRODUCTION: persist purchase_key and purchase_body BEFORE sending.
# If a timeout occurs, retry with that saved key and exact body.
lease = api("POST", "/leases", purchase_body, purchase_key)["data"]
print("Lease", lease["id"], "charged", lease["amount"], lease["currency"])// Node.js 18+ · server-side only · purchases ONE lease up to USD 0.42.
// Set PREPROX_API_BASE and PREPROX_API_KEY in your environment first.
import { randomUUID } from 'node:crypto';
const base = process.env.PREPROX_API_BASE.replace(/\/$/, '');
const key = process.env.PREPROX_API_KEY;
const maxPrice = '0.42'; // Review this ceiling before running.
const cents = value => {
const [whole, fraction = ''] = value.split('.');
return BigInt(whole) * 100n + BigInt(fraction.padEnd(2, '0'));
};
async function api(method, path, body, purchaseKey) {
const response = await fetch(base + path, {
method,
headers: {
Authorization: `Bearer ${key}`, Accept: 'application/json',
...(body ? { 'Content-Type': 'application/json' } : {}),
...(purchaseKey ? { 'Idempotency-Key': purchaseKey } : {}),
},
body: body ? JSON.stringify(body) : undefined,
signal: AbortSignal.timeout(30000),
});
const result = await response.json();
if (!response.ok) throw new Error(`HTTP ${response.status}: ${JSON.stringify(result)}`);
return result;
}
const { data: account } = await api('GET', '/account');
if (cents(account.wallet_balance) < cents(maxPrice)) throw new Error('Fund your wallet first.');
const inventory = await api('GET', '/proxies?country=US&plan=shared');
const proxy = inventory.data.find(p => p.plans.shared.available
&& cents(p.plans.shared.amount) <= cents(maxPrice));
if (!proxy) throw new Error('No match on this page; check meta.next_cursor or adjust filters.');
const { data: quote } = await api('POST', '/quotes', { proxy_id: proxy.id, plan: 'shared' });
const purchaseKey = randomUUID();
const purchaseBody = { quote_id: quote.id, max_price: maxPrice };
// PRODUCTION: persist purchaseKey and purchaseBody BEFORE sending.
// If a timeout occurs, retry with that saved key and exact body.
const { data: lease } = await api('POST', '/leases', purchaseBody, purchaseKey);
console.log({ lease_id: lease.id, amount: lease.amount, currency: lease.currency });The final request purchases a real lease. USD 0.42 is an example ceiling, not a published price. Review current quotes and your ceiling first. Python and Node.js use the environment variables shown in the cURL example. Save the purchase body and idempotency key before sending in production.
All paths are relative to the base URL and require a bearer key. JSON responses use a data envelope. Expand an endpoint for parameters and response details.
/accountAccount & walletRead your account ID, name, email, and current USD wallet balance. Your API key always acts on the account that created it.
No parameters.
/proxiesBrowse proxy inventoryFind available shared and private static marketplace proxy plans: 24-hour lease periods with unlimited bandwidth, subject to the acceptable-use policy. Mobile and WiFi availability varies. Prices are PreProx customer prices. Inventory masks IPs and excludes connection credentials.
Query: country (2-letter code), state, city, zip (max 20), isp, connection_type (wifi | cell), plan (shared | private), min_stars (integer 1–5), cursor (opaque numeric string, max 30).
/proxies/{proxy_id}Get a proxyRead current details, pricing, and plan availability for an inventory item. Use the complete px_ ID from discovery without parsing or changing it.
Path: proxy_id (opaque px_ string).
/quotesCreate a quoteGet a five-minute quote for a shared or private 24-hour static proxy lease. The five-minute quote expiry is the checkout deadline, not the lease duration. Quotes belong to your account and do not reserve inventory or debit your wallet.
Body: proxy_id (required opaque inventory ID), plan (required: shared | private).
{
"proxy_id": "px_YOUR_INVENTORY_ID",
"plan": "shared"
}/leasesPurchase a leasePurchase one 24-hour static proxy lease using a valid quote and your maximum accepted USD price. Proxy bandwidth is unlimited, subject to the acceptable-use policy. Requires an Idempotency-Key header (8–128 letters, numbers, dots, underscores, colons, or hyphens). Persist the key and body before sending.
Body: quote_id (required q_ ID), max_price (required USD decimal, 0.01–999999.99, up to 2 decimal places).
{
"quote_id": "q_YOUR_QUOTE_ID",
"max_price": "0.42"
}/leasesList your leasesList marketplace leases owned by your account. Records show saved status and usage; refresh an individual lease for current reconciliation.
Query: status (active | expired | cancelled), page (1–1000000), per_page (1–100, default 20).
/leases/{lease_id}Get a leaseRead an owned lease and its connection credentials. Store and display the response securely.
Path: lease_id (numeric ID returned by your purchase).
/leases/{lease_id}/refreshRefresh a leaseReconcile current usage, status, expiry, and any observed renewal. Renewals authorized by auto-renew can debit your wallet during reconciliation.
Path: lease_id (owned numeric ID). No body required.
/leases/{lease_id}/auto-renewSet auto-renewEnable or disable automatic renewal into additional billable 24-hour lease periods. Enabling authorizes future wallet charges. API key expiry does not change the lease period or its auto-renew setting. Any observed renewal already owed is settled before the setting changes; a 402 leaves the setting unchanged.
Path: lease_id. Body: enabled (required boolean).
{
"enabled": false
}/leases/{lease_id}/whitelistSet an allowed IPSet the IP address used for IP-based authentication on an owned active lease.
Path: lease_id. Body: ip (required valid IPv4 or IPv6 address).
{
"ip": "203.0.113.10"
}/leases/{lease_id}Cancel & request a refundRequest a wallet refund for an active, unused lease with confirmed eligibility. Current usage must be verified. Repeating a successful cancellation does not credit your wallet twice. If refund_pending is returned, contact support for reconciliation.
Path: lease_id (owned numeric ID). No body required.
Lease responses include connection.host, port, username, password, whitelist_ip, no_auth_host, and no_auth_port. Unavailable fields can be null. Treat these responses as credentials. Timestamps use ISO 8601 UTC.
The API uses the same PreProx marketplace selling prices and pricing rules as the website. Your account’s USD wallet pays per 24-hour lease, with unlimited proxy bandwidth during that lease under the acceptable-use policy. There is no per-GB billing for these leases. The quote’s amount is your customer price.
max_price is the most you authorize for the purchase. Checkout will not charge above your ceiling or the confirmed quote. If pricing changes or inventory disappears, resolve the error and request a fresh quote.
Use decimal arithmetic for money. Auto-renew authorizes future wallet charges; maintain sufficient funds or disable renewal before expiry. Refunds require current, confirmed eligibility and credit the wallet once. An unused lease is not a guarantee of a refund.
Every purchase requires an Idempotency-Key. Create one unique key per intended purchase and persist it with the exact JSON body before sending. A retry with the same account, key, and body returns the original lease without a second debit, with Idempotency-Replayed: true. A changed body returns 409.
Retry the original body with the same purchase key. A new key represents a new purchase.
For purchase_pending or purchase_uncertain, keep the key and contact support before submitting another purchase.
All your keys also share an account limit of 60 requests and 10 mutations per minute. IP limits apply before authentication. Follow Retry-After on a 429. Never automatically retry a failed purchase with a new key.
Use X-RateLimit-Limit and X-RateLimit-Remaining to pace a key. X-RateLimit-Account-Limit and X-RateLimit-Account-Remaining show the account-wide request allowance. Fix authorization, validation, balance, and quote errors before retrying. A failed insufficient-balance attempt requires wallet funding, a fresh quote, and a new purchase key after resolving that attempt.
Errors return a consistent JSON envelope. Validation failures include field details. Keep the X-Request-ID header or request_id when contacting support.
{
"error": {
"code": "validation_failed",
"message": "The request parameters are invalid.",
"details": {
"plan": [
"The selected plan is invalid."
]
}
},
"request_id": "YOUR_REQUEST_ID"
}
| HTTP | Meaning | Next step |
|---|---|---|
| 401 | Invalid, expired, or revoked key | Check your key or create a replacement. |
| 402 | Insufficient wallet balance | Fund your wallet and resolve the failed attempt. |
| 403 | Missing scope or unavailable account | Check permissions and account eligibility. |
| 404 | Resource not found | Check the ID and that you own the lease. |
| 409 | Quote, purchase, or refund conflict | Read the error code; reconcile uncertain purchases. |
| 422 | Invalid request fields | Correct the fields or idempotency header. |
| 429 | Rate limit reached | Wait for Retry-After before retrying. |
| 502 | Operation temporarily unavailable | Retry safely; preserve the original purchase key. |
| 503 | API access is paused | Try later or contact support. |
Share your request ID and a redacted description. Keep API keys and connection passwords private.