Quick answer
How do I use a mobile proxy in Python with IP rotation?
Pass the proxy URL http://USERNAME:[email protected]: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
| 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.
import requests
PROXY = "http://USERNAME:[email protected]: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>'}import requests
# socks5h: the proxy resolves the hostname, not your machine
PROXY = "socks5h://USERNAME:[email protected]: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.
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.
import requests
PROXY = "http://USERNAME:[email protected]: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 exampleHow 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.
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}:[email protected]: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.