# How to use a mobile proxy in Python, with IP rotation

> Python code for 4G/5G mobile proxies: requests and httpx over HTTP or SOCKS5, rotate the IP via API, handle 429 limits, sticky sessions. No KYC.

- URL: https://cellmast.com/guides/python-mobile-proxy/
- Last updated: 2026-10-13
- Publisher: CellMast (https://cellmast.com)

Copy-ready Python for a CellMast dedicated port or the rotating mobile pool: connect, rotate, wait for the new address, and retry without hammering the API.

**Quick answer — How do I use a mobile proxy in Python with IP rotation?**

Pass the proxy URL `http://USERNAME:PASSWORD@gw.cellmast.com:7777` to `requests` or `httpx`, then call `POST /api/v1/mobile/{portId}/rotate` with your API key when you want a new carrier IP. Wait for the answer, which usually takes 5–15 seconds, and respect the 30-second gap between rotations. **CellMast** dedicated 4G/5G ports start at $2.63/day, no KYC, paid in crypto.

## What you need

| Attribute | Value |
| --- | --- |
| Python | 3.10 or newer |
| Libraries | `requests` (HTTP), `requests[socks]` or `httpx[socks]` for SOCKS5 |
| Gateway | `gw.cellmast.com`, HTTP port 7777, SOCKS5 port 7778 |
| Port credentials | Username and password from the client area; after support moves a port, read its host, ports and password again in the client area, because they can change |
| API key | With the `proxies` scope, for rotation |
| Rotating pool username | `USERNAME-country-{cc}-session-{id}-ttl-{minutes}` |

## How do I send a request through a mobile port?

Set the same proxy URL for `http` and `https`. For HTTPS targets, `requests` opens a CONNECT tunnel through the gateway, so the target sees the carrier IP and your TLS stays end to end.

*requests over HTTP*

```python
import requests

PROXY = "http://USERNAME:PASSWORD@gw.cellmast.com:7777"
proxies = {"http": PROXY, "https": PROXY}

r = requests.get("https://api.ipify.org?format=json", proxies=proxies, timeout=30)
print(r.json())  # {'ip': '<carrier IP>'}
```

*SOCKS5 (pip install "requests[socks]")*

```python
import requests

# socks5h: the proxy resolves the hostname, not your machine
PROXY = "socks5h://USERNAME:PASSWORD@gw.cellmast.com:7778"
r = requests.get("https://api.ipify.org", proxies={"http": PROXY, "https": PROXY}, timeout=30)
print(r.text)
```

## How do I rotate the IP from Python?

Wrap the rotation call in a helper that understands the 429 answer. The helper below waits for `Retry-After` when you rotate too soon, then checks that the carrier really gave a new address.

*Rotation helper*

```python
import time
import requests

API = "https://cellmast.com/api/v1"
KEY = "API_KEY"

def rotate(port_id: str, tries: int = 3) -> str:
    """Ask the modem for a new carrier IP and return it."""
    for _ in range(tries):
        r = requests.post(f"{API}/mobile/{port_id}/rotate",
                          headers={"Authorization": f"Bearer {KEY}"}, timeout=60)
        if r.status_code == 429:  # rotation_too_soon
            time.sleep(int(r.headers.get("Retry-After", "30")))
            continue
        r.raise_for_status()
        data = r.json()
        if data["ip"] != data.get("previousIp"):
            return data["ip"]
        time.sleep(30)  # same IP from the carrier: wait and try again
    raise RuntimeError("no new IP after several tries")

print("new IP:", rotate("PORT_ID"))
```

## How do I rotate between jobs, not inside them?

Run a whole job on one address, then rotate before the next one. This keeps cookies and logins consistent inside a job and gives each job a fresh address.

*One IP per job*

```python
import requests

PROXY = "http://USERNAME:PASSWORD@gw.cellmast.com:7777"

def run_job(urls):
    with requests.Session() as s:
        s.proxies = {"http": PROXY, "https": PROXY}
        for url in urls:
            resp = s.get(url, timeout=30)
            print(resp.status_code, url)

jobs = [["https://example.com/a", "https://example.com/b"],
        ["https://example.com/c"]]
for urls in jobs:
    run_job(urls)
    rotate("PORT_ID")  # helper from the previous example
```

## How do I use the rotating pool with sticky sessions in httpx?

On the per-GB pool there is no rotation call: the username decides. Without a session id, each new connection gets a new IP. HTTP clients keep connections open (keep-alive), so for a new IP per request open a new client for each request, or send `Connection: close`. With `session-<id>-ttl-<minutes>`, requests keep one IP for that time.

*httpx (pip install httpx)*

```python
import uuid
import httpx

def pool_client(country: str = "us", minutes: int | None = None) -> httpx.Client:
    user = f"USERNAME-country-{country}"
    if minutes:
        user += f"-session-{uuid.uuid4().hex[:8]}-ttl-{minutes}"
    proxy = f"http://{user}:PASSWORD@gw.cellmast.com:7777"
    return httpx.Client(proxy=proxy, timeout=30)

with pool_client("gb", minutes=10) as c:   # same UK mobile IP for 10 minutes
    print(c.get("https://api.ipify.org").text)
    print(c.get("https://api.ipify.org").text)
```

## Which errors should my script handle?

- **HTTP 429 from the rotation API:** you rotated less than 30 seconds ago. Wait for `Retry-After`.
- **HTTP 409 `port_not_active`:** the port expired or is suspended. Check the client area.
- **Proxy connection errors just after a rotation:** normal; the modem is reconnecting. Retry after a short pause.
- **HTTP 407 from the gateway:** wrong username or password for the port.
- **Targets answering 403 or 429:** slow down first, then rotate once. Mobile IPs are shared, and a calmer pace fixes most of these.

## Python and mobile proxies: questions

### Should I use HTTP or SOCKS5 in Python?

HTTP is simpler and works with plain `requests`. SOCKS5 needs the `requests[socks]` extra but carries any TCP traffic, and `socks5h://` resolves DNS on the proxy side instead of your machine. Both reach the same CellMast modem: HTTP on port 7777, SOCKS5 on port 7778.

### Can I use asyncio with a mobile proxy?

Yes. `httpx.AsyncClient(proxy=...)` and `aiohttp` both accept an HTTP proxy URL. Keep concurrency moderate on a single dedicated port: it is one modem on one carrier connection, so dozens of parallel requests share the same radio link.

### How do I make Selenium or Playwright use the port?

In Playwright, pass `proxy={"server": "http://gw.cellmast.com:7777", "username": "USERNAME", "password": "PASSWORD"}` to `launch()` or `new_context()`. Selenium's proxy options take no password: answer the proxy login through Selenium 4 BiDi network authentication, or use Playwright. Rotate between browser contexts, never while a page is loading.

**Get a port and an API key** Dedicated 4G/5G ports from $2.63/day, rotating mobile data from $1.50/GB. Pay in crypto. [See pricing](https://cellmast.com/pricing/) · [Mobile API reference](https://cellmast.com/docs/api/mobile/)

---

CellMast: CellMast is a 4G/5G mobile proxy provider: dedicated carrier modems with unlimited traffic, plus a rotating per-GB mobile pool, paid in crypto with no ID upload.
