How to use a mobile proxy with Python
Updated 5 October 2026
Send requests and headless-browser traffic through a T-Proxy UK mobile proxy, and get a fresh IP from your script.
187.124.210.93 or 187.124.113.127, depending on which of our servers the proxy is on. Replace HOST, HTTP_PORT, SOCKS_PORT, USERNAME and PASSWORD in the examples with yours.requests over HTTP
The requests library takes a proxy URL with the username and password in it. Use the same HTTP proxy URL for both http and https keys: HTTPS sites are tunnelled through it, so the proxy never sees the page content.
import requests
PROXY = "http://USERNAME:PASSWORD@HOST:HTTP_PORT"
proxies = {"http": PROXY, "https": PROXY}
r = requests.get("https://api.ipify.org", proxies=proxies, timeout=30)
print(r.text) # the proxy's UK mobile IP
api.ipify.org only answers over IPv4, so it always shows the proxy’s IPv4 address. To see the address most sites will see, use api64.ipify.org: if your proxy prefers IPv6 (the default on SIMs that have it), that prints an IPv6 address.
SOCKS5
SOCKS5 support in requests needs one extra package:
$ pip install "requests[socks]"
Then use your SOCKS5 port with the socks5h:// scheme. The h matters: it makes the proxy look up domain names, so DNS goes through the UK mobile connection too instead of your own network.
import requests
PROXY = "socks5h://USERNAME:PASSWORD@HOST:SOCKS_PORT"
proxies = {"http": PROXY, "https": PROXY}
r = requests.get("https://api64.ipify.org", proxies=proxies, timeout=30)
print(r.text)
Reuse connections with a Session
For more than a few requests, use a Session. It keeps connections to the proxy open between requests, which is noticeably faster over a mobile network, and keeps cookies like a browser would.
import requests
session = requests.Session()
session.proxies = {
"http": "http://USERNAME:PASSWORD@HOST:HTTP_PORT",
"https": "http://USERNAME:PASSWORD@HOST:HTTP_PORT",
}
for url in ["https://api.ipify.org", "https://api64.ipify.org"]:
r = session.get(url, timeout=30)
print(url, r.status_code, r.text)
Rotate the IP from Python
Each proxy has a Rotation URL on its page. A plain GET to it, with no login, asks the modem for a new IP address. It replies with a short JSON message once the modem has its new address: "result": "success", or "fail" with a reason.
import time
import requests
ROTATION_URL = "YOUR_ROTATION_URL" # from your proxy page
PROXY = "http://USERNAME:PASSWORD@HOST:HTTP_PORT"
proxies = {"http": PROXY, "https": PROXY}
def current_ip():
return requests.get("https://api.ipify.org", proxies=proxies, timeout=30).text
def rotate():
# The call returns when the modem has its new address. That can take
# up to a couple of minutes, so allow a long timeout.
reply = requests.get(ROTATION_URL, timeout=180).json()
if reply.get("result") != "success":
raise RuntimeError(f"rotation refused: {{reply}}")
# Wait until the proxy answers again before sending real traffic.
for _ in range(30):
try:
return current_ip()
except requests.RequestException:
time.sleep(5)
raise RuntimeError("proxy did not come back after rotating")
print("before:", current_ip())
print("after: ", rotate())
- A rotation usually takes well under a minute, and occasionally up to about two. The proxy drops its connections while the modem reconnects, so pause your work until
rotate()returns. - Rotations requested too close together are refused. Rotate per batch or per session, and leave at least a minute between rotations.
- Sometimes the carrier hands the modem the same IPv4 address back. If you need a different one, check
current_ip()and rotate again after the wait. - Keep the Rotation URL private: anyone who has it can rotate your proxy.
Playwright (headless browser)
Playwright takes the proxy server, username and password as separate fields when you launch the browser:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(proxy={
"server": "http://HOST:HTTP_PORT",
"username": "USERNAME",
"password": "PASSWORD",
})
page = browser.new_page()
page.goto("https://api.ipify.org")
print(page.inner_text("body"))
browser.close()
socks5:// server and a password fails with “Browser does not support socks5 proxy authentication”. The HTTP port works the same way and carries HTTPS sites without any problem.To use different proxies in one browser, pass the same proxy dictionary to browser.new_context(proxy=...) instead, one context per proxy.
Tips
- Always set a timeout. Mobile connections occasionally stall, and requests waits forever by default. 30 seconds is a sensible start.
- Retry on connection errors. Catch
requests.RequestException, wait a few seconds and retry, especially around a rotation. - Keep credentials out of your code. Read them from environment variables, for example
os.environ["PROXY_URL"]. - Special characters. T-Proxy usernames and passwords are letters and digits. If you use your own credentials with symbols in a proxy URL, URL-encode them (
@becomes%40). - Several proxies. Run one proxy per worker or per carrier. The Reseller API can claim, rotate and extend proxies from code.
- Behave like a person. Keep request rates reasonable and respect each site’s terms. See our acceptable use policy.
Questions
Should I use the HTTP or the SOCKS5 port?
For requests either works. HTTP needs no extra packages and works in Playwright with Chromium; SOCKS5 with socks5h:// also carries non-HTTP traffic. The same username and password work on both.
Why does my script show an IPv6 address?
Proxies on SIMs with IPv6 prefer it by default, and sites that support IPv6 see that address. You can switch a proxy to IPv4 first with the Default IP setting on its proxy page.
Does this work with Scrapy, httpx or Selenium?
Yes. Anything that accepts an HTTP or SOCKS5 proxy with a username and password works with the same details; only the setting name differs.
How often can I rotate?
Leave at least a minute between rotations; calls too close together are refused. A rotation itself usually takes under a minute.
More guides
Need a UK mobile proxy?
Real 4G and 5G IPs on EE, O2, Three, Sky and Lyca. Plans from £4 a day.