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.
If you're weighing Rayobyte as well, Using Rayobyte Proxies With Python explains which of its products fits, and Rayobyte vs Geonode vs Webshare for Python Scrapers puts it side by side with Geonode and Webshare.
Residential tip: Rayobyte is worth testing when you need precise targeting: its residential proxies can be pinned to a country, state, city, ZIP code or ASN, with sticky sessions from 1 to 120 minutes. More in using Rayobyte with Python.
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.
Sources and further reading
Independent references that back up the points above, from standards bodies, governments, universities and non-profits. They open in a new tab.
- urllib.request documentation (Python Software Foundation): Python's standard library documentation, including ProxyHandler.
- RFC 9110: HTTP Semantics (IETF / RFC Editor): The HTTP standard that defines how proxies, tunnels and the CONNECT method behave.
- Downloader Middleware (Scrapy documentation): Scrapy's documentation for the middleware where proxy rotation lives.
- CONNECT request method (MDN Web Docs (Mozilla)): How browsers open an HTTPS tunnel through an HTTP proxy.
- RFC 1929: Username/Password Authentication for SOCKS V5 (IETF / RFC Editor): How SOCKS5 proxies check a username and password.
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.