Same code, different URLs
In Python, both Webshare and Geonode are just proxy URLs:
http://USERNAME:PASSWORD@HOST:PORT
socks5h://USERNAME:PASSWORD@HOST:PORTThe differences are in hosts, ports and how the username carries options (rotate, session, location). Provider guides: Webshare with Python and Geonode with Python.
A provider-agnostic helper
Keep provider details in one place, so the rest of your code never cares which provider it uses:
import os, random
PROVIDERS = {
"webshare_res": {
"host": "p.webshare.io:80",
"user": lambda s: f"{os.environ['WS_USER']}-{s}" if s else f"{os.environ['WS_USER']}-rotate",
"pw": os.environ["WS_PASS"],
},
"geonode_res": {
"host": os.environ["GN_HOST"], # from the Geonode dashboard
"user": lambda s: os.environ["GN_USER"] + (f"-session-{s}" if s else ""), # follow Geonode's documented format
"pw": os.environ["GN_PASS"],
},
}
def proxies(name, session=None):
p = PROVIDERS[name]
url = f"http://{p['user'](session)}:{p['pw']}@{p['host']}"
return {"http": url, "https": url}The username formats above are placeholders; generate the exact formats in each provider's dashboard.
requests, HTTPX and aiohttp
All three work with both providers:
- requests:
requests.get(url, proxies=proxies("geonode_res"), timeout=30) - HTTPX:
httpx.Client(proxy=url) - aiohttp:
session.get(url, proxy=url)
For SOCKS5, install requests[socks] (or httpx[socks]) and use socks5h:// so DNS goes through the proxy.
Sessions and rotation
| Need | Webshare | Geonode |
|---|---|---|
| New IP per request | Rotate suffix on backbone, or rotate a direct list | Rotating gateway |
| Same IP for a flow | Session suffix | Session ID, lifetime up to 24 hours |
| Fixed IPs | Datacenter and static residential lists | ISP proxies |
Use one requests.Session per flow, so cookies and IP stay together.
Async concurrency
Both providers have practical concurrency limits: Webshare plans have thread limits; residential gateways on either provider can slow down if you open too many connections at once. Use a semaphore and measure:
sem = asyncio.Semaphore(50)Raise it gradually while watching error rates. See Webshare bandwidth and threads.
Proxy tip: To test the Geonode side of this comparison, a small residential balance from Geonode is enough, and it doesn't expire if you pause. See our complete Geonode guide for its full product range.
Cost by job type
| Python job | Better fit |
|---|---|
| HTML scraping of lenient sites | Webshare datacenter list |
| API polling at high frequency | Webshare datacenter list |
| Protected sites | Geonode residential, test Webshare |
| Rendered pages without a browser | Geonode Scraper API from Python |
Verdict
Python treats both identically. Use a helper like the one above, test both on your targets, and route each target to the cheapest product that works.
Measuring both providers from Python
import time, statistics, requests
def measure(proxies, url, n=100):
ok, times = 0, []
for _ in range(n):
t = time.time()
try:
r = requests.get(url, proxies=proxies, timeout=30)
ok += r.ok and "captcha" not in r.text.lower()
except requests.RequestException:
pass
times.append(time.time() - t)
return ok / n, statistics.median(times)
for name in ("webshare_res", "geonode_res"):
print(name, measure(proxies(name), "https://target.example/page"))Run it at a few times of day and on each important target.
Async tips
For aiohttp or HTTPX async clients, pass the proxy per request, cap concurrency with a semaphore, and reuse the client. Create a fresh connection when you need a guaranteed new IP from a rotating gateway.
Budget tip: The cheapest way to settle this comparison is to test both: Webshare has a free datacenter plan, and Geonode offers a low-cost residential trial. Run the same targets through each. See using Webshare with Python.
Keeping provider code testable
Mock the proxies() helper in unit tests so tests never hit real proxies. Keep a separate integration test that runs one request through each provider to catch credential or format changes early.
A real-world example
A data engineer's Python pipeline pulls from 50 sources. A proxies() helper maps each source to webshare_dc, webshare_res or geonode_res. A nightly benchmark sends 50 requests per source through the alternative provider and logs results. When a source's alternative is consistently cheaper per success for two weeks, the mapping is updated in config. The pipeline code itself never changes.
Not sure this is the right proxy type for the job? The best proxies in 2026 guide compares residential, ISP, datacenter and mobile options, and our cheap proxies guide covers budget picks that still work.
Key takeaways
- Both are standard proxy URLs in requests, HTTPX and aiohttp.
- A provider-agnostic helper keeps provider details in one place.
- Use one session per flow so cookies and IP stay together.
- Cap async concurrency and measure errors as you ramp up.
- Benchmark both on your targets and route by cost per success.
FAQ
Do Webshare and Geonode work with Python requests?
Yes, with standard proxy URLs.
Can I call Geonode's Scraper API from Python?
Yes, it's a regular HTTP API. Webshare doesn't offer a scraper API.
Which is faster from Python?
It depends on targets and locations. Measure median and 95th percentile latency on both.
Can I use both providers in one requests Session?
Use one session per provider and flow, since a session holds one proxy setting.
Does HTTPX support SOCKS5 for both?
Yes, with httpx[socks] installed.
How do I keep credentials out of Python code?
Read them from environment variables or a secrets manager.
Editorial note: Proxy providers change their pools, features and prices often, so treat any figures here as typical ranges at the time of writing and confirm current terms with the provider before you buy.