Developer API
The Hell World personal API lets your own programs and AI tools read your products, usage and balance and generate proxy lines for the products you own.
API at a glance
- REST base URL:
https://hellworld.io/hellworld/papi/v1 - OpenAPI 3.1: https://hellworld.io/hellworld/papi/v1/openapi.json
- MCP endpoint:
https://hellworld.io/mcp - Auth:
Authorization: Bearer <your key>orX-API-Key: <your key> - Format: Every response is JSON except /proxies/export, which returns plain text.
It is for server-side use: requests that carry a browser Origin header are rejected with 403 CORS_NOT_ALLOWED.
Authentication
Key format: hwp_live_<12 letters or digits>.<43 characters>
Authorization: Bearer <your key>
X-API-Key: <your key>Expiry: at least 1 hour and at most 1 year from now; the key page suggests 30 days.
Each account has one key. It has full access to the API and must have an expiry date.
Issuing, regenerating and extending a key require a code sent to your account email. By default, viewing the key again also requires one, except within 10 minutes of a verified action.
Send the key in the Authorization header as a Bearer token or in the X-API-Key header. If you send both they must be identical. Keys in query strings are not accepted.
Regenerating a key invalidates the old one immediately. Regenerate it if you think it has leaked.
Endpoints
Paths are relative to https://hellworld.io/hellworld/papi/v1.
| Method | Path | What it returns |
|---|---|---|
GET | /me | Your key prefix, masked email, the client IP the API sees, server time and rate limits. |
GET | /products | Your products with status, usage and generation capabilities. No credentials. |
GET | /products/{product} | One product by id or code. A code shared by several of your products returns 409 PRODUCT_AMBIGUOUS with candidate ids. |
GET | /products/{product}/locations/{kind} | Location codes accepted by generate for this product (countries, states, cities, asns, isps). |
POST | /proxies/generate | Generate proxy lines as JSON. |
GET | /proxies/export | The same lines as plain text, one per line. Parameters go in the query string; format=json is not available. |
GET | /usage | Usage per product with its source (upstream, cached, local or unknown) and the traffic total. |
GET | /balance | Your balance in USD (read-only) with a link to top up on the website. |
GET | /openapi.json | The OpenAPI 3.1 description of this API. No key needed. |
Generating proxies
| Parameter | Meaning |
|---|---|
product required | Product id (32 hex characters) or product code, e.g. oxylab. See /products. |
count | Number of lines: 1-1000, default 1 (1-100 over MCP). Ignored for static ISP products, which return their full list. |
country | Country code, e.g. US. Omit for a random location. |
state | State or region code; see locations/states. Some products take state or city but not both (sending both returns 400 INVALID_PARAMETER for state). |
city | City code; see locations/cities. |
isp | ISP code (ET-Hearth only); see locations/isps. |
asn | ASN from 1 to 4294967295. Cannot be combined with state, city or zip. |
zip | ZIP code, only where the product capabilities list zip. |
os | OS fingerprint value from the product capabilities. |
session | rotating (default) or sticky. |
session_minutes | Sticky session length; allowed values are in capabilities.session.sticky_minutes. |
session_seed | Only with session=sticky. The same seed, product and parameters give the same session identifiers; it does not promise the same exit IP. |
server | Gateway region from capabilities.servers. |
protocol | http (default) or socks5, where the product capabilities list it. |
format | Output format, default host:port:user:pass. |
Formats: host:port:user:pass user:pass@host:port user:pass:host:port url json
Generating lines never creates or changes anything at the proxy provider: no accounts, orders or quotas are touched.
For ET-Hearth targeting, country, state, city and ISP codes are checked against live provider data. When that data is not cached it is fetched from the provider; if it is unavailable the request fails with 503 LOCATIONS_UNAVAILABLE.
If a product does not support the requested targeting, the API returns 400 UNSUPPORTED_PARAMETER; you never silently get a broader proxy.
Colon and at-sign formats reject credentials that contain ":", "@", whitespace or newlines (400 FORMAT_UNSAFE); use url or json instead.
A static ISP product returns its full list over REST (up to 1000 lines). Over MCP it returns at most 100 lines; for a longer list use GET /proxies/export.
session_seed only keeps session identifiers stable. It does not promise the same exit IP.
Security
Generated proxy lines contain your proxy username and password. Any program or AI platform you connect receives them.
Usage and balance
status is a display classification based on Hell World's local records. It is not permission to generate and not a live guarantee from the provider. Whether a product can generate is decided by the eligibility check of that generate request.
usage.source tells you where a number comes from: upstream (read from the provider during this request), cached (read from the provider within the last 10 minutes; synced_at says when), local (recorded by Hell World, not read from the provider) or unknown. Only some products are read from the provider; for the others it is local or unknown and synced_at is null.
usage with source upstream or cached is read from the provider and may lag behind a top-up that just completed. Its limit, used and remaining are the provider's current figures for the product and can differ from what you bought.
traffic_total adds up only products whose traffic numbers are trusted.
The balance is read-only. Top up on the website.
Errors
{"error": {"code", "message", "param", "hint", "docs_url"}, "request_id"}Branch on error.code, not on message text.
429 and 503 responses may carry a Retry-After header (seconds). 429 RATE_LIMITED also names the exhausted limit in error.limit_dimension.
Include request_id when you contact support.
| Code | HTTP status | Meaning |
|---|---|---|
ACCOUNT_SUSPENDED | 403 | The account is suspended. |
AUTH_STATUS_INVALID | 503 | The account status is inconsistent. Contact support. |
AUTH_STATUS_UNAVAILABLE | 503 | The key or account status could not be checked. Retry shortly. |
CORS_NOT_ALLOWED | 403 | The request came from a browser (Origin header). Call the API from a server. |
FORMAT_UNSAFE | 400 | The chosen format cannot represent these credentials safely; use url or json. |
GENERATOR_OUTPUT_TOO_LARGE | 409, 500 | The result exceeds a size limit. 409 means a static ISP list is longer than MCP allows; use /proxies/export. |
GENERATOR_UNAVAILABLE | 503 | Generation is temporarily unavailable. Retry shortly. |
INTERNAL_ERROR | 500 (and other 5xx) | Unexpected server error. |
INVALID_PARAMETER | 400 | A parameter is missing or invalid; error.param names it. |
INVALID_REQUEST | 400 (and other 4xx) | The request itself is malformed, e.g. the body is not a JSON object. |
KEY_INVALID | 401 | The key is wrong, revoked or expired. |
LOCATIONS_UNAVAILABLE | 503 | Live location data is temporarily unavailable. Retry shortly. |
METHOD_NOT_ALLOWED | 405 | This path does not accept this HTTP method. |
NOT_ACCEPTABLE | 406 | The Accept header excludes every type this path returns. |
NOT_FOUND | 404 | No such path, or the personal API is not enabled. |
PAYLOAD_TOO_LARGE | 413 | The request body is too large. |
PRODUCT_AMBIGUOUS | 409 | The code matches several of your products; use one of the candidate ids. |
PRODUCT_DATA_INVALID | 409 | This product's connection data is incomplete or too large. Contact support. |
PRODUCT_INACTIVE | 409 | The product is expired or not active. |
PRODUCT_NOT_FOUND | 404 | No such product in your account. |
PRODUCT_PROVISIONING | 409 | The product is still being set up. |
RATE_LIMITED | 429 | A rate limit or generation budget was exceeded; see Retry-After and limit_dimension. |
RATE_LIMIT_UNAVAILABLE | 503 | Rate limiting is temporarily unavailable. Retry shortly. |
UNAUTHENTICATED | 401 | No key, or a malformed key, was sent. |
UNSUPPORTED_MEDIA_TYPE | 415 | The Content-Type is not supported; send application/json. |
UNSUPPORTED_PARAMETER | 400 | This product does not support the requested targeting or option. |
Rate limits
- Per client IP: 600 requests per minute.
- Per key: 120 read requests and 60 generation requests per minute.
- Per account: 300 requests, 20,000 generated lines and 5,000,000 bytes per minute, and 4 generations at a time.
Headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset X-Budget-Lines-Remaining
Read endpoints count against the read limit; generate and export count against the generation limit.
Every MCP request that the key check admits counts as one generation-class request (see the MCP section).
X-RateLimit-* describe the key limit for the current category; X-Budget-Lines-Remaining is on generation responses.
MCP server for AI tools
Endpoint https://hellworld.io/mcp, protocol versions 2025-06-18 and 2026-07-28.
Authentication is a static API key in a request header. Hell World does not implement OAuth for MCP, so clients that can only connect with OAuth cannot use it yet.
Responses are always JSON. There is no SSE stream and no subscriptions.
A successful tool result carries structuredContent plus the same JSON as a text part, and is at most 2 x the REST response plus 4 KiB. This wrapping does not count against the byte budget.
An error result has isError set and only a text part: the REST error envelope unchanged, or a short MCP error such as RESPONSE_TOO_LARGE. It has no structuredContent.
If a REST response behind a tool is larger than 256 KiB, the tool returns RESPONSE_TOO_LARGE; use the REST API for that request.
Tools
| Tool | What it does |
|---|---|
list_products | Lists your Hell World products with status, usage and generation capabilities. No credentials. |
get_product | One of your products by id or code. If a code matches several of your products the error lists candidate ids. |
list_locations | Location codes accepted by generate_proxies for this product. states, cities, asns and isps need country; cities and isps (ET-Hearth) also need state. |
generate_proxies not idempotent | Generates proxy lines for one of your products (count 1-100 per call; a static ISP product returns its full list, at most 100 lines over MCP). Lines contain your proxy username and password. Unsupported targeting is an error, never a broader proxy. |
get_usage | Usage per product with its source (upstream, cached, local or unknown) and the traffic total. |
get_balance | Your account balance in USD (read-only) with the website top-up link. |
What counts against your limitsLimit counting
| Situation | Per-IP limit | Per-key and account limits |
|---|---|---|
| Rejected at the MCP entry before any key check: wrong path, wrong Host, a browser Origin, a method other than POST, the server is busy, the client address is missing or invalid, or the key header is sent twice. | not counted | not counted |
| The personal API is switched off: the key check answers 404 NOT_FOUND. | not counted | not counted |
| The key check fails: no key, a malformed, wrong, revoked or expired key, a suspended account, or the account status cannot be read. The error is returned as the REST API would return it. | counted | not counted |
| The key or user limit is exhausted (429 RATE_LIMITED with Retry-After) or rate limiting is unavailable (503 RATE_LIMIT_UNAVAILABLE). | counted | not counted |
| The per-IP limit is exhausted (429). | not counted | not counted |
| The key check admits the request. From here on it counts once whatever happens next: success, a body that is too large, invalid JSON, a batch, a subscription request, a protocol error from the MCP library, or a tool that fails. | counted | counted |
| A tool calling the REST API on your behalf. It is not counted again; generate_proxies still reserves and settles its line and byte budget. | not counted | not counted |
| The key check answered but the answer was lost or unusable (AUTH_STATUS_UNAVAILABLE or INTERNAL_ERROR from the MCP server). The request may have been counted once. | may be counted | may be counted |
MCP errors
HTTP-level errors from the MCP server:
| Code | HTTP status | Meaning |
|---|---|---|
HOST_NOT_ALLOWED | 403 | The Host header is not hellworld.io. |
CORS_NOT_ALLOWED | 403 | The request came from a browser. |
NOT_FOUND | 404 | The path is not /mcp. |
METHOD_NOT_ALLOWED | 405 | Only POST is supported. |
INVALID_REQUEST | 400 | The client address is missing or the key header was sent twice. |
MCP_BUSY | 503 | Too many concurrent requests; retry after Retry-After seconds. |
PAYLOAD_TOO_LARGE | 413 | The request body is larger than 64 KiB. |
AUTH_STATUS_UNAVAILABLE | 503 | The key check did not give a usable answer; retry shortly. |
INTERNAL_ERROR | 500 | Unexpected error in the MCP server. |
JSON-RPC errors:
| Code | HTTP status | Meaning |
|---|---|---|
-32700 | 400 | Parse error: the body is not valid JSON. |
-32600 | 400 | Invalid request: a batch or a non-object body. |
-32601 | 200 | Method not found: subscriptions are not offered. |
-32603 | 500 | Internal error, including a response that would exceed 1 MiB. |
-32020 | 400 | The Mcp-Method, Mcp-Name or MCP-Protocol-Version header does not match the request body. |
-32000 | 400 | Unsupported protocol version on a 2025 request. |
The pinned MCP library may also return other standard JSON-RPC errors.
Tool error codes (in the text of a result with isError set):
| Code | Meaning |
|---|---|
RESPONSE_TOO_LARGE | The REST response behind this tool is larger than 256 KiB; use the REST API for this request. |
API_UNAVAILABLE | The API could not be reached; retry shortly. |
INVALID_PARAMETER | A product or kind value cannot be used in a request path. |
GENERATOR_OUTPUT_TOO_LARGE | The wrapped tool result would exceed 2 x the REST response plus 4 KiB. |
INTERNAL_ERROR | The API returned something unexpected. |
When the key check fails, the MCP server returns the REST error unchanged (status, body, Retry-After and request id).
Connecting a client
Claude Code — .mcp.json (project) — safe to commit because it holds no secret:
{
"mcpServers": {
"hellworld": {
"type": "http",
"url": "https://hellworld.io/mcp",
"headers": {
"Authorization": "Bearer ${HELLWORLD_API_KEY}"
}
}
}
}Cursor — ~/.cursor/mcp.json (global, outside every repository):
{
"mcpServers": {
"hellworld": {
"url": "https://hellworld.io/mcp",
"headers": {
"Authorization": "Bearer ${env:HELLWORLD_API_KEY}"
}
}
}
}Set the variable without leaving the key in your shell history:
read -rs HELLWORLD_API_KEY && export HELLWORLD_API_KEYWARNING
Keep the key in an environment variable or a password manager. Never put the real key on a command line (it ends up in shell history and process lists), never commit it to a repository, and never paste it into an issue or chat.
WARNING
Do not use claude mcp add --header with the real key; reference the environment variable in .mcp.json instead.
OpenAPI
The OpenAPI 3.1 document describes all nine operations, their parameters and every error code.
It is served without a key once the personal API is enabled.
Tools that import OpenAPI, such as GPT Actions, can use it with an API key header.