Mobile Proxies US logo
Guide

The Mobile Proxy API: List, Rotate and Check a Line From Code

Published

Every line you buy from Mobile Proxies US is reachable two ways: as a proxy (host, port, username, password) and as a licence in the account API. The API is what you use when a script, not a person, needs to know which lines exist, what their exit IP is right now, and when to request a new one. This page walks the three operations that cover almost every integration: list, rotate, check. The base URL is https://cp.mobileproxiesus.com/backend/api_v1 and the key is on the API page of the dashboard.

Authentication: one key per account

The dashboard's API page generates one API key per account. Send it in the x-api-key header on every keyed request. Treat it like a password: it reaches every line on the account, and if it ends up in a repository, tell support at once and get it out of the history.

The key identifies the account, not a line. There is no per-line key, so if two separate systems need access, give each system the key through its own secret store rather than copying it into source. Every keyed request counts against a budget of 300 requests per minute per account; over that you get 429 with a Retry-After header, and the right response is to wait that many seconds.

curl -s https://cp.mobileproxiesus.com/backend/api_v1/proxies/my \
  -H "x-api-key: $MPUS_API_KEY"

GET /proxies/my: the list call

The list call returns {"proxyList": [...]} with one element per licence. The fields scripts use most: uuid, license_status, carrier, city, network_tier, host, http_port, socket_port, authentication_user (a username:password string), expired_date, status (CONNECTED or DISCONNECTED, the modem link), rotation_link, ip_history_link, vless_link, capabilities and min_time_change_ip.

Scripts normally call this at start-up and cache the result. The licence uuid is the stable handle: it survives a free move to another metro, as do the username, password and remaining term. Host and ports can change on a move, because the line lands on another server, so re-read /proxies/my after one. city is the location as sold, such as 5G Houston. sim_location says where the address shows right now, by the SIM behind it.

{
  "proxyList": [{
    "uuid": "221215fb-e831-4d08-a224-d321301b9845",
    "license_status": "ACTIVE",
    "carrier": "T-Mobile",
    "city": "5G Houston",
    "network_tier": "5G",
    "host": "HOST",
    "http_port": 8101,
    "socket_port": 5101,
    "authentication_user": "username:password",
    "expired_date": "2026-12-01T14:03:00.000Z",
    "status": "CONNECTED",
    "rotation_link": "https://ROTATION_HOST/backend/api_v1/proxy/change-ip?license=221215fb-...",
    "ip_history_link": "https://cp.mobileproxiesus.com/backend/api_v1/proxies/221215fb-.../ip-history",
    "vless_link": "vless://...",
    "min_time_change_ip": 0
  }]
}

GET rotation_link: request a new exit IP

Rotation is a plain GET on the line's rotation_link. It takes no API key, because the licence uuid in the URL is the credential, so treat the link as a secret: anyone holding it can rotate the line and read its status. Read the link from the list call rather than building it. It can sit on a rotation host that differs from the dashboard host, and it can come in a short /c/TOKEN form.

On phone lines the reply comes back in about a second and the new IP lands 10 to 15 seconds later; add confirm_ip=1 to hold the reply until the new IP is confirmed, usually 10 to 20 seconds and at most about 90. Do not retry a rotation that is still running. There is no limit on how many rotations you make. min_time_change_ip is the wait in minutes the rotation link holds that line to, 0 meaning none, and phone lines also have their own short cooldown of 1 to 2 minutes. A rotation inside either wait is refused with HTTP 400 and a JSON message saying why.

curl -s "$ROTATION_LINK"
# phone line, hold the reply until the new IP is confirmed
curl -s "$ROTATION_LINK&confirm_ip=1"

GET /proxy/status: the status read

GET /proxy/status?license=UUID returns the live state of one line: ip, httpPort, sockPort and status. It takes no key and returns no credentials. Scripts use it for two things: to wait for a rotation to land, and to verify that the proxy they are about to use is up before they commit a job to it. Note that status reports the modem link only.

For more, POST /proxy/health with x-api-key and a JSON body of license_uuid and days returns current.public_ip, uptime episodes, rotation outcomes and daily usage over up to 30 days. For a second opinion from the outside, make a request through the proxy itself to any IP echo service and compare.

import os, time, requests
BASE = "https://cp.mobileproxiesus.com/backend/api_v1"
H = {"x-api-key": os.environ["MPUS_API_KEY"]}
def rotate_and_wait(line, timeout=90):
    status = f"{BASE}/proxy/status"
    args = {"license": line["uuid"]}
    before = requests.get(status, params=args, timeout=15).json()["ip"]
    r = requests.get(line["rotation_link"], timeout=30)
    if r.status_code == 400:
        raise RuntimeError(r.json()["message"])
    t0 = time.time()
    while time.time() - t0 < timeout:
        now = requests.get(status, params=args, timeout=15).json()["ip"]
        if now and now != before:
            return now
        time.sleep(3)
    raise TimeoutError("rotation did not land")

Error handling and status codes

Errors arrive as JSON with a message field, such as API key is invalid. 400 on a rotation means it was refused, usually inside the line's wait; the message says how long to wait. 429 means the account budget is spent, so honour Retry-After. 403 with code account_suspended means the key's account is suspended. 404 from /proxy/status means the licence expired, was released or was reassigned.

Design for the expiry case explicitly. A line that lapses does not throw an error through the proxy, it simply stops authenticating. A nightly job that lists lines, checks license_status and expired_date against its own configuration, catches an expired plan before a batch fails at 3 a.m. Webhooks can push the same news: license.expiring, license.expired, proxy.down and proxy.rotation_failed are all available from the account settings.

What else it does, and where the key must not go

The same key covers more than the three reads above: POST /proxy/purchase buys a line, POST /license/extendproxy extends one, POST /proxy/move-location moves one, POST /license/update-rotation-time sets auto-rotation and POST /proxy/update-authentication changes the login. There is no shared pool behind any of this: each uuid maps to one SIM in one device that is yours for the term.

Keep the key out of client-side code. Browser extensions, mobile apps and anything shipped to end users should talk to your own backend, which holds the key. The rotation link is lighter, since it only reaches one line, so it can live in a cron job or a webhook, but it is still a secret and should be stored as one.

Frequently asked

Is there a rate limit?

300 requests per minute per account on keyed requests. Past that the API answers 429 with a Retry-After header. Spending endpoints such as purchases have smaller budgets of their own.

Can I rotate without the API key?

Yes. A GET on the line's rotation_link rotates it with no key. The licence uuid in the link is the credential, so keep the link private.

Does the API tell me when a line is about to expire?

The list call carries license_status and expired_date in UTC, and a license.expiring webhook fires within 24 hours of the end. You can extend over the API with POST /license/extendproxy.

Why does a rotation sometimes come back as 400?

It was refused, usually because it fell inside min_time_change_ip or a phone line's own cooldown of 1 to 2 minutes. The JSON message says how long to wait.

USA mobile proxies on hardware we own

Real 4G and 5G carrier exit IPs, eight US metros; unlimited rotation, sticky sessions, HTTP(S) or SOCKS5. An endpoint costs $2 for the first two hours or $5 per day; paid hours are credited against the day.

View plans See all locations