How to Use a Mobile Proxy with cURL and Python Requests (2026)
How to Use a Mobile Proxy with cURL and Python Requests (2026)
You bought a mobile proxy and the provider handed you one cryptic line. A host, a port, a username, and a password, and no obvious next step. This guide turns those four values into a working request that returns a real Singapore carrier ip, first with curl, then with python requests.
I run a hardware mobile proxy farm in Singapore. Real phones, real sim cards from SingTel, M1, and StarHub. So I set up these exact connections every day, and almost every problem people hit is one of about five small things. Here is the path that works, and the traps that break it.
What your four values mean
Write down your host, port, username, and password, because every command below reuses them. On my farm the port is the important one to understand. Each port maps to exactly one physical phone on one tower, so when you connect you are borrowing one real device, not a slice of a pool. That is why the exit ip looks like a normal Singapore consumer to the sites you visit.
Prove it with curl first
Before any code, prove the line works with curl. If curl works, your credentials and network are fine and you can stop guessing. The -x flag sets the proxy, and we point it at an ip echo endpoint.
curl -x http://USER:PASS@HOST:PORT --max-time 10 https://api.ipify.org?format=json
Look at the ip it prints. That is not your ip, it is the carrier ip of one of my phones in Singapore. If you see a SingTel, M1, or StarHub address, the proxy works. The --max-time matters: a wrong port hangs until it times out, so failing fast saves you staring at a frozen terminal.
The socks5h variant and why the h matters
If your provider exposes socks5, swap the scheme. Use socks5h, not plain socks5.
curl -x socks5h://USER:PASS@HOST:PORT --max-time 10 https://api.ipify.org?format=json
That trailing h is the whole point. Plain socks5 resolves dns on your own machine, so even though traffic exits through my Singapore phone, your computer still asks your real isp to look up the domain. That is a dns leak, and it quietly exposes where you really are. socks5h sends the hostname through the tunnel so the proxy resolves it. Use socks5h for any real work.
The same thing in python requests
In requests the proxy lives in a dictionary with two keys, http and https, both pointing at the same url. Pass it as proxies and verify the result.
import requests
proxies = {
"http": "http://USER:PASS@HOST:PORT",
"https": "http://USER:PASS@HOST:PORT",
}
r = requests.get("https://api.ipify.org?format=json", proxies=proxies, timeout=20)
print(r.json())
If r.json() shows the carrier ip and not your home ip, your python is wired correctly. Do not skip this check. Verifying the exit ip once at the start saves you from a whole scrape that quietly ran on your own address.
Set both keys, every time
Forgetting the https key trips up more people than anything else. If you only set the http key, your plain http requests go through the proxy but your https requests go straight out on your real ip, and almost everything is https now. Set both keys even when they are identical.
socks5h in python needs the socks extra
requests does not speak socks out of the box. Install it with the socks extra, then use a socks5h url in the same dictionary.
pip install "requests[socks]"
proxies = {
"http": "socks5h://USER:PASS@HOST:PORT",
"https": "socks5h://USER:PASS@HOST:PORT",
}
Same shape, same two keys, just the socks5h scheme so dns resolves remotely.
Use a session for sticky reuse
For anything that logs in, create a session and put the proxies on it. Every call through that session reuses the connection and stays on the same phone, which matters because a login that jumps to a new ip halfway through looks like fraud to the target.
session = requests.Session()
session.proxies.update(proxies)
r = session.get("https://api.ipify.org?format=json", timeout=20)
A session also keeps the connection warm. The first request pays the full cost of opening the tunnel and the tls handshake, which on a mobile line can be a few hundred milliseconds. Every request after that is quicker. And set a generous read timeout, fifteen to thirty seconds, because a real radio has higher latency and can blink during a tower handoff. Many proxy failures are just a client that gave up too early.
The five things that break it
A 407 means the proxy refused your credentials, either a wrong username or password, or your own ip is not on the allowlist for the account. The other four: forgetting the https key so https leaks your real ip, using socks5 instead of socks5h so dns leaks, leftover http_proxy or https_proxy environment variables that override or fight your code, and simply never verifying the exit ip. When something behaves strangely, check your environment first.
Finish by verifying both things
The finish line is always the same two checks. Confirm the exit ip is the carrier ip and not yours, and confirm dns resolves remotely by using socks5h. When both are true, you are running clean.
Try it on real Singapore mobile ips
If you want creds that behave exactly like this, start a free trial of Singapore Mobile Proxy. Real SG ips from SingTel, M1, and StarHub, with sticky sessions and dns that routes through the tunnel so you stop leaking your real resolver. Use code YT30 on signup, then paste your host and port into the curl line and the python dictionary above and you are running.
Get new guides and videos first — join the Telegram channel.