Fixing Proxy URL had no scheme

The proxy is written without http:// in front. urllib3 refuses it; newer requests and pip guess instead, which turns the same mistake into vaguer errors.

5 min readTested on urllib3 2.8 · requests 2.34 and 2.25 · Selenium 4.51 · pip 26.2
A proxy written as host:port without http:// makes urllib3, Selenium and older requests raise Proxy URL had no scheme; newer requests adds the scheme itself and httpx says Unknown scheme for proxy URL.proxy = "via.proxies.vision:9000"urllib3.ProxyManagerProxySchemeUnknown: Proxy URL had no schemeSelenium (HTTPS_PROXY)ProxySchemeUnknown: Proxy URL had no schemerequests 2.25InvalidURL: Proxy URL had no schemerequests 2.34adds http:// itself …httpxUnknown scheme for proxy URLurllib3 2.8 · requests 2.34 and 2.25 · Selenium 4.51 · httpx 0.28 · October 22, 2026

In short

Write the proxy as a full URL: http://USER:PASS@host:port. Check HTTPS_PROXY, HTTP_PROXY and ALL_PROXY too: a variable set to host:port causes the same error in code that never mentions a proxy.

http://USER:PASS@host:portHTTPS_PROXY

The message comes from urllib3, the HTTP library under requests, pip, Selenium and many others. Given a proxy like via.proxies.vision:9000, it won’t assume http://:

txt
urllib3.exceptions.ProxySchemeUnknown: Proxy URL had no scheme, should start with http:// or https://

Nothing was sent. We passed the same schemeless proxy to each library:

WhereWhat you see
urllib3.ProxyManager(…)ProxySchemeUnknown: Proxy URL had no scheme, should start with http:// or https://
Selenium webdriver.Remote() with HTTPS_PROXY=host:portProxySchemeUnknown: Proxy URL had no scheme, should start with http:// or https://
requests 2.25InvalidURL: Proxy URL had no scheme, should start with http:// or https://
requests 2.34adds http:// itself (see below)
httpx 0.28ValueError: Unknown scheme for proxy URL URL('via.proxies.vision:9000')
host:port:user:pass in requestsInvalidURL: Failed to parse: '…' is not a valid host or port
Fig. 1 — Python 3.13 (requests 2.25 on Python 3.9), October 22, 2026. Proxy written as via.proxies.vision:9000 or USER:PASS@via.proxies.vision:9000.

The variable nobody looked at

Selenium is the common surprise. Its remote connection reads HTTPS_PROXY on its own, so a variable left as host:port by a shell profile or a CI setting breaks webdriver.Remote() even though your script sets no proxy. With http:// in the variable, the same script got past it. If the grid is inside your network, add its host to NO_PROXY so it isn’t reached through the proxy.

host:port:user:pass is a list format

Proxy lists and many tools use host:port:user:pass. Libraries don’t: they want a URL. Rearrange it to http://user:pass@host:port.

Newer requests adds http:// to a proxy without a scheme instead of raising. That works for host:port. With a login it depends on the username, because name:password@host:port already looks like a scheme followed by a colon:

InvalidProxyURLalice:secret@via.proxies.vision:9000"alice" read as the scheme
reaches the proxyuser_1:secret@via.proxies.vision:9000_ can't be in a scheme
reaches the proxyhttp://alice:secret@via.proxies.vision:9000scheme written out

The first line fails with Please check proxy URL. It is malformed and could be missing the host., a message that points nowhere near the cause. Code that worked with one account can break with the next. Always write the scheme.

pip sends its downloads through the same libraries, but it doesn’t show the proxy error. A proxy that refuses the connection turns into a missing package:

txt
ERROR: Could not find a version that satisfies the requirement six (from versions: none)
ERROR: No matching distribution found for six

-v isn’t enough; with -vvv the cause appears, here a proxy given without a login: Could not fetch URL https://pypi.org/simple/six/: proxy connection error: ('Unable to connect to proxy', OSError('Tunnel connection failed: 407 Proxy Authentication Required')). A username of letters only (--proxy alice:secret@host:port) fails like requests above. The fix is the same: --proxy http://USER:PASS@host:port, or the scheme in HTTPS_PROXY. pip and SOCKS proxies.

A setup that works

Ran unchanged on Python 3.13 with requests 2.34 and pip 26.2.

fetch_proxy.py
import os
from urllib.parse import quote

import requests

user = quote(os.environ["PROXY_USER"] + "-country-de", safe="")
password = quote(os.environ["PROXY_PASS"], safe="")

# Always write the scheme. Without it, a username like "alice" is read as the scheme,
# and urllib3, Selenium and older requests refuse the URL outright.
proxy = f"http://{user}:{password}@via.proxies.vision:9000"

r = requests.get("https://ipinfo.io/json", proxies={"http": proxy, "https": proxy}, timeout=30)
print(r.status_code, r.text)
terminal
export HTTPS_PROXY="http://$PROXY_USER-country-de:$PROXY_PASS@via.proxies.vision:9000"
export HTTP_PROXY="$HTTPS_PROXY"
pip download --no-deps -d /tmp/pkgs six

Special characters

quote(…, safe="") encodes characters like @ or : in the login, which would otherwise end the username early. In a shell variable, percent-encode them by hand (@ becomes %40).

http://, even for https:// sites

The scheme describes how you talk to the proxy, not the website. Our port 9000 speaks plain HTTP and opens an encrypted tunnel to the site; https:// there fails differently. What that looks like.

What does 'Proxy URL had no scheme, should start with http:// or https://' mean?
urllib3 got a proxy written as host:port or user:pass@host:port, without http:// in front, and refuses to guess. Write the full URL: http://user:pass@host:port. The proxy and your login are fine; nothing was sent yet.
Why do I get it from Selenium?
Selenium's remote connection reads HTTPS_PROXY and HTTP_PROXY and hands them to urllib3. If one of them is set to host:port without http://, webdriver.Remote() fails with ProxySchemeUnknown before it talks to the grid (Selenium 4.51 in our test). Fix the variable, and add the grid's host to NO_PROXY if it shouldn't go through the proxy at all.
Why doesn't requests show this error any more?
Newer requests adds http:// to a proxy without a scheme itself. requests 2.25 raised InvalidURL: Proxy URL had no scheme; requests 2.34 just tried http://. That hides the problem rather than fixing it: a username made only of letters is then read as the scheme, and the request fails with 'Please check proxy URL. It is malformed and could be missing the host.'
pip says 'No matching distribution found'. Can that be the proxy?
Yes. pip turns a proxy that refuses the connection into 'Could not find a version that satisfies the requirement' and 'No matching distribution found'. Run it with -vvv to see the real cause, for example Tunnel connection failed: 407 Proxy Authentication Required. Then pass ‑‑proxy http://user:pass@host:port.
What does httpx say instead?
httpx raises ValueError: Unknown scheme for proxy URL URL('host:port'). Same fix: put http:// in front.

Residential proxies, pay per GB

HTTP and SOCKS5. Country, city and sticky sessions in the username. No subscription.