Products
Datacenter proxies from $19/mo Rotating proxies from $25/mo ISP proxies from $33/mo Dedicated proxies from $3.50/mo UDP proxies from $5/mo Try proxies
Use cases
Data & scraping AI services Social media & messaging E-commerce & finance Media & entertainment Marketing & ads Automation & tools All use cases →
Pricing
Full pricing table All locations Money-back guarantee
Resources
Dashboard guide API reference API and MCP Setup guides FAQ Blog For business About us Affiliate program
New dashboard
English
English Русский

Dedicated proxies

3 endpoints · base URL https://papaproxy.net/account_new · authentication

List dedicated-proxy countries

GET/api/v1/billing/dedicated/countries
No API key required

Countries with dedicated IPs in stock and the number of available IPs. Only countries with at least one IP are listed.

No API key required. Use the same geo_source and product_kind in quote and order requests.

Parameters

FieldTypeDescription
geo_source (query)stringGeo source for country lookups: maxmind (geolocation) or ripe (RIR allocation). Use the same value in countries, quote, and order requests.One of: maxmind, ripeDefault: "maxmind"
product_kind (query)stringDedicated datacenter (proxy_datacenter) or dedicated ISP (proxy_isp) proxies.One of: proxy_datacenter, proxy_ispDefault: "proxy_datacenter"

Request example Try it in the Dashboard

cURL
curl -X GET "https://papaproxy.net/account_new/api/v1/billing/dedicated/countries"
Python
import requests

resp = requests.get(
    "https://papaproxy.net/account_new/api/v1/billing/dedicated/countries",
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
Node.js
const resp = await fetch("https://papaproxy.net/account_new/api/v1/billing/dedicated/countries", {
  method: "GET",
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
PHP
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/billing/dedicated/countries');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, err := http.NewRequest("GET", "https://papaproxy.net/account_new/api/v1/billing/dedicated/countries", nil)
	if err != nil {
		panic(err)
	}
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}

Responses

  • 200 Countries with dedicated IPs in stock. · 6 fields
    Example response · JSON
    {
      "countries": [
        {
          "country": "IL",
          "available_ips": 453
        }
      ],
      "geo_source": "maxmind",
      "product_kind": "proxy_datacenter",
      "offered_kinds": [
        "proxy_datacenter",
        "proxy_isp"
      ]
    }
    FieldTypeDescription
    countriesarray of objectCountries with at least one IP available.
    countries[].country requiredstringISO 3166-1 alpha-2 country code.
    countries[].available_ips requiredintegerNumber of dedicated IPs currently available.
    geo_sourcestringGeo source the counts are for.One of: maxmind, ripeDefault: "maxmind"
    product_kindstringProduct the counts are for.One of: proxy_datacenter, proxy_ispDefault: "proxy_datacenter"
    offered_kindsarray of stringDedicated products you can order.
  • 422 Validation error: a field is missing or has the wrong type or value.
    Example · JSON
    {
      "detail": "Validation error"
    }
  • 429 Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.
    Example · JSON
    {
      "detail": "Too Many Requests"
    }

Get a dedicated-proxy quote

POST/api/v1/billing/dedicated/quote
API key optional

Price dedicated proxies: from 1 IP per order, with no per-country minimum. The quote doesn't reserve IPs.

  • Countries are ISO codes only. A country that's out of stock still gets a price: check that segments[].available is at least count before ordering, or the order fails with 409.
  • The per-IP rate (unit_millicents) depends on the total IP count; term discounts apply on top.
  • Pass total_price_cents to the order as expected_total_cents.

The API key is optional.

Request body

FieldTypeDescription
segments requiredarray of objectOne or more countries with IP counts.Min items: 1
segments[].country requiredstringISO 3166-1 alpha-2 country code ("IL", "US"). Numeric IDs aren't accepted.
segments[].count requiredintegerNumber of dedicated IPs in this country. From 1.Minimum: 1
product_kindstringDedicated datacenter (proxy_datacenter) or dedicated ISP (proxy_isp) proxies.One of: proxy_datacenter, proxy_ispDefault: "proxy_datacenter"
period_monthsintegerTerm in months. Longer terms get a discount: 10% for 3 months, 15% for 6, 20% for 12.One of: 1, 3, 6, 12Default: 1
geo_sourcestringGeo source for country lookups: maxmind (geolocation) or ripe (RIR allocation). Use the same value in countries, quote, and order requests.One of: maxmind, ripeDefault: "maxmind"
promo_codestring, nullableOptional promo code.
udp_unlockbooleanAdd UDP (50% of the base price).Default: false
extra_connections_countintegerPaid concurrent connections beyond those included.Default: 0
extra_whitelist_countintegerPaid whitelisted IPs beyond the free allowance.Default: 0

Request example Try it in the Dashboard

cURL
curl -X POST "https://papaproxy.net/account_new/api/v1/billing/dedicated/quote" \
  -H "Content-Type: application/json" \
  -d '{"segments": [{"country": "IL", "count": 2}], "period_months": 3}'
Python
import requests

resp = requests.post(
    "https://papaproxy.net/account_new/api/v1/billing/dedicated/quote",
    json={
        "segments": [
            {
                "country": "IL",
                "count": 2
            }
        ],
        "period_months": 3
    },
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
Node.js
const resp = await fetch("https://papaproxy.net/account_new/api/v1/billing/dedicated/quote", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "segments": [
      {
        "country": "IL",
        "count": 2
      }
    ],
    "period_months": 3
  }),
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
PHP
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/billing/dedicated/quote');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'segments' => [[
            'country' => 'IL',
            'count' => 2
        ]],
        'period_months' => 3
    ]),
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
Go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	req, err := http.NewRequest("POST", "https://papaproxy.net/account_new/api/v1/billing/dedicated/quote", strings.NewReader(`{"segments": [{"country": "IL", "count": 2}], "period_months": 3}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}

Responses

  • 200 Price quote. Check segments[].available before ordering. · 20 fields
    Example response · JSON
    {
      "unit_millicents": 220000,
      "total_price_cents": 1188,
      "ip_count": 2,
      "min_ips_per_order": 1,
      "segments": [
        {
          "country": "IL",
          "count": 2,
          "available": 453
        }
      ],
      "geo_source": "maxmind",
      "product_kind": "proxy_datacenter",
      "dedicated_class": "dc",
      "period_months": 3,
      "monthly_price_cents": 440,
      "segment_monthly_cents": 440,
      "addon_monthly_cents": 0,
      "discount_pct": 10,
      "partner_discount_pct": null,
      "promo_code": null,
      "promo_discount_cents": 0,
      "total_before_promo_cents": 1188
    }
    FieldTypeDescription
    unit_millicentsintegerMonthly price per IP, in millicents (thousandths of a cent). Depends on the total IP count.
    total_price_centsintegerTotal for the whole term, in cents. Pass it as expected_total_cents when ordering.
    ip_countintegerTotal number of IPs.
    min_ips_per_orderintegerMinimum IPs per order (1 for dedicated proxies).
    segmentsarray of objectRequested countries with current stock.
    segments[].countrystringISO 3166-1 alpha-2 country code.
    segments[].countintegerRequested number of IPs.
    segments[].availableintegerIPs currently in stock. If it's lower than count, an order fails with 409 dedicated_out_of_stock.
    geo_sourcestringGeo source used.One of: maxmind, ripeDefault: "maxmind"
    product_kindstringProduct priced.One of: proxy_datacenter, proxy_ispDefault: "proxy_datacenter"
    dedicated_classstringdc for datacenter, isp for ISP.
    period_monthsintegerTerm in months.
    monthly_price_centsintegerMonthly price, including add-ons, before the term discount.
    segment_monthly_centsintegerMonthly price of the IPs alone.
    addon_monthly_centsintegerMonthly price of add-ons.
    discount_pctintegerTerm discount, in percent.
    partner_discount_pctinteger, nullablePartner discount, in percent, if your account has one.
    promo_codestring, nullableApplied promo code.
    promo_discount_centsintegerPromo discount, in cents.
    total_before_promo_centsintegerTotal before the promo discount, in cents.
  • 422 Validation error: an empty segments list, a count below 1, a country that isn't an ISO code, or an unsupported period_months.
    Example · JSON
    {
      "detail": "Validation error"
    }
  • 429 Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.
    Example · JSON
    {
      "detail": "Too Many Requests"
    }
  • 500 Currently returned for an unrecognized promo_code instead of a validation error. Check the promo code and retry without it. — error format

Order dedicated proxies

POST/api/v1/billing/dedicated/order
API key required scope services:write

Buy dedicated proxies — IPs reserved exclusively for you — from 1 IP. Get the price from POST /api/v1/billing/dedicated/quote first.

  • Send the Idempotency-Key header (1–128 characters). A retry with the same key and body returns the original order and doesn't charge again (balance_applied_cents is 0 in the repeated response). The same key with a different body returns 400. The key goes in the header, not in the body.
  • expected_total_cents is required: pass total_price_cents from the quote. If the price has changed, the response is 409 with detail.code = "price_changed" and the current actual_total_cents.
  • If a country doesn't have enough IPs, the response is 409 with detail.code = "dedicated_out_of_stock" and the shortfall per country.
  • whitelist_ips must contain at least one IPv4 address.
  • With use_balance=true, your wallet balance is applied first; if it covers the total, the service is active right away. Otherwise, and with use_balance=false (the default), the service is pending until amount_due_cents is paid in the Dashboard under Pending payments.
  • Fields that other order endpoints accept — idempotency_key, trial, addons, expected_price_cents — are rejected here with 422.

Parameters

FieldTypeDescription
Idempotency-Key (header) requiredstringUnique key for this order. Reuse it only to retry the same request.Min length: 1Max length: 128

Request body

FieldTypeDescription
segments requiredarray of objectOne or more countries with IP counts.Min items: 1
segments[].country requiredstringISO 3166-1 alpha-2 country code ("IL", "US"). Numeric IDs aren't accepted.
segments[].count requiredintegerNumber of dedicated IPs in this country. From 1.Minimum: 1
expected_total_cents requiredintegertotal_price_cents from the quote you showed the user. Without it the response is 422; if the price has changed, 409 with the current actual_total_cents.
whitelist_ips requiredarray of stringIPv4 addresses to whitelist. At least one is required.Min items: 1
product_kindstringDedicated datacenter (proxy_datacenter) or dedicated ISP (proxy_isp) proxies.One of: proxy_datacenter, proxy_ispDefault: "proxy_datacenter"
period_monthsintegerTerm in months. Longer terms get a discount: 10% for 3 months, 15% for 6, 20% for 12.One of: 1, 3, 6, 12Default: 1
geo_sourcestringGeo source for country lookups: maxmind (geolocation) or ripe (RIR allocation). Use the same value in countries, quote, and order requests.One of: maxmind, ripeDefault: "maxmind"
use_balancebooleanApply your wallet balance first. Default: false — the service is created as pending and the full amount is due in the Dashboard under Pending payments.
auto_renewbooleanRenew automatically when the term ends.
promo_codestring, nullableOptional promo code.
udp_unlockbooleanAdd UDP (50% of the base price).Default: false
extra_connections_countintegerPaid concurrent connections beyond those included.Default: 0
extra_whitelist_countintegerPaid whitelisted IPs beyond the free allowance.Default: 0

Request example Try it in the Dashboard

cURL
curl -X POST "https://papaproxy.net/account_new/api/v1/billing/dedicated/order" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY" \
  -H "Idempotency-Key: dedicated-order-2026-001" \
  -H "Content-Type: application/json" \
  -d '{"segments": [{"country": "IL", "count": 1}], "expected_total_cents": 220, "whitelist_ips": ["203.0.113.10"], "use_balance": true}'
Python
import os

import requests

resp = requests.post(
    "https://papaproxy.net/account_new/api/v1/billing/dedicated/order",
    headers={
        "Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}",
        "Idempotency-Key": "dedicated-order-2026-001",
    },
    json={
        "segments": [
            {
                "country": "IL",
                "count": 1
            }
        ],
        "expected_total_cents": 220,
        "whitelist_ips": [
            "203.0.113.10"
        ],
        "use_balance": True
    },
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
Node.js
const resp = await fetch("https://papaproxy.net/account_new/api/v1/billing/dedicated/order", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
    "Idempotency-Key": "dedicated-order-2026-001",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "segments": [
      {
        "country": "IL",
        "count": 1
      }
    ],
    "expected_total_cents": 220,
    "whitelist_ips": [
      "203.0.113.10"
    ],
    "use_balance": true
  }),
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
PHP
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/billing/dedicated/order');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
        'Idempotency-Key: dedicated-order-2026-001',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'segments' => [[
            'country' => 'IL',
            'count' => 1
        ]],
        'expected_total_cents' => 220,
        'whitelist_ips' => ['203.0.113.10'],
        'use_balance' => true
    ]),
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
Go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("POST", "https://papaproxy.net/account_new/api/v1/billing/dedicated/order", strings.NewReader(`{"segments": [{"country": "IL", "count": 1}], "expected_total_cents": 220, "whitelist_ips": ["203.0.113.10"], "use_balance": true}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	req.Header.Set("Idempotency-Key", "dedicated-order-2026-001")
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}

Responses

  • 201 The order was created. Check payment_required and amount_due_cents. · 10 fields
    Example response · JSON
    {
      "service_id": "1300d2ec-f511-573c-9869-93c88c501084",
      "status": "active",
      "ip_count": 1,
      "total_price_cents": 220,
      "period_months": 1,
      "monthly_price_cents": 220,
      "balance_applied_cents": 220,
      "amount_due_cents": 0,
      "payment_required": false,
      "intent_id": null
    }
    FieldTypeDescription
    service_idstring (uuid)ID of the new service.
    statusstringactive when the order is paid, pending while amount_due_cents is unpaid.
    ip_countintegerNumber of IPs ordered.
    total_price_centsintegerTotal for the term, in cents.
    period_monthsintegerTerm in months.
    monthly_price_centsintegerMonthly price, in cents.
    balance_applied_centsintegerPart of the total covered by your wallet balance. A retry with the same Idempotency-Key returns 0 here, because nothing is charged again.
    amount_due_centsintegerAmount still to be paid, in cents.
    payment_requiredbooleantrue when amount_due_cents must still be paid in the Dashboard.
    intent_idstring (uuid), nullableID of the pending payment, if any.
  • 400 The Idempotency-Key was already used with a different request body.
    Example · JSON
    {
      "detail": "Idempotency-Key reused with a different dedicated order body"
    }
  • 401 The API key is missing, malformed, revoked, or expired, or the account is inactive.
    Example · JSON
    {
      "detail": "Invalid or revoked API key."
    }
  • 403 The API key lacks scope services:write.
    Example · JSON
    {
      "detail": "API key is missing required scope: services:write"
    }
  • 409 The price changed, or a country doesn't have enough IPs in stock. Nothing is charged.
    Example · price changed · JSON
    {
      "detail": {
        "code": "price_changed",
        "actual_total_cents": 220
      }
    }
    Example · out of stock · JSON
    {
      "detail": {
        "code": "dedicated_out_of_stock",
        "per_country": {
          "US": {
            "requested": 1,
            "available": 0
          }
        }
      }
    }
  • 422 Validation error, a missing Idempotency-Key header or expected_total_cents, or no whitelisted IP.
    Example · idempotency key required · JSON
    {
      "detail": {
        "code": "idempotency_key_required",
        "message": "Idempotency-Key header is required (1..128 chars)."
      }
    }
    Example · price confirmation required · JSON
    {
      "detail": {
        "code": "price_confirmation_required",
        "message": "expected_total_cents is required (price confirmation)."
      }
    }
    Example · whitelist required · JSON
    {
      "detail": {
        "error": "WHITELIST_REQUIRED",
        "message": "A proxy service requires at least one whitelisted IP at order time. …"
      }
    }
  • 429 Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.
    Example · JSON
    {
      "detail": "Too Many Requests"
    }

Last updated: November 9, 2026. Generated from the OpenAPI 3.1 specification (API version 0.1.0). Markdown version for AI agents.