Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Requests raises requests.exceptions.MissingSchema when the URL it is preparing has no parsed scheme, usually https:// or http://. Make the destination an absolute URL, inspect the exact value immediately before the request, and check proxy URLs separately. A typical correction is:

import requests

url = "https://example.com"
response = requests.get(url, timeout=30)
print(response.status_code)

If the URL has a scheme but no host, Requests reports a different InvalidURL error, so the distinction helps you choose the right fix.

What the MissingSchema error means

When Requests prepares a request, it parses the URL before opening a network connection. In Requests 2.34.2, a destination without a scheme follows the missing-scheme path and produces an error similar to:

Invalid URL ...: No scheme supplied. Perhaps you meant https://...?

A scheme is the protocol prefix at the start of an absolute web address:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • https://example.com/products has the https scheme.
  • http://intranet.example/products has the http scheme.
  • example.com/products has no scheme and can trigger MissingSchema.
  • /products/1 is a relative path, not a complete request URL.

Requests must also know the host. A value such as https:///products has a scheme but no host and is handled as InvalidURL: No host supplied, not MissingSchema.

Fix it in a reliable order

1. Inspect the runtime value, not the value you intended to pass

The variable shown in your editor may not be the value reaching Requests. Log its representation and type immediately before the call:

import requests

print("url:", repr(url))
print("type:", type(url).__name__)
response = requests.get(url, timeout=30)

repr() exposes an empty string, hidden whitespace, or the literal value None. The type check catches code that accidentally passes a list, dictionary, or another object instead of a string.

Typical runtime values and their meanings are:

Runtime value What it indicates Action
'example.com' Domain without a scheme Prefix the correct protocol.
'/products/1' Relative scraped link Resolve it against the page’s absolute URL.
None Extraction, configuration, or assignment returned no value Trace the assignment and reject it before the request.
'' Empty configuration or input Validate the input and provide a real URL.

2. Supply a complete absolute URL

Use the protocol that is valid for the service:

import requests

secure = requests.get("https://api.example.com/v1/items", timeout=30)
legacy = requests.get("http://intranet.example/items", timeout=30)

Do not add https:// mechanically if the target is an internal service that only supports HTTP; choose the scheme required by that endpoint.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

3. Validate before calling Requests

A small validation function turns a cryptic exception into a local, actionable error:

from urllib.parse import urlparse
import requests


def require_absolute_http_url(value):
    if not isinstance(value, str):
        raise TypeError(f"URL must be a string, got {type(value).__name__}")

    candidate = value.strip()
    parsed = urlparse(candidate)
    if parsed.scheme not in {"http", "https"}:
        raise ValueError(
            f"URL must start with http:// or https://; received {candidate!r}"
        )
    if not parsed.netloc:
        raise ValueError(f"URL has a scheme but no host: {candidate!r}")
    return candidate

url = require_absolute_http_url("https://example.com")
response = requests.get(url, timeout=30)
response.raise_for_status()

This check intentionally accepts only web schemes. If your application supports another protocol through a custom adapter, adapt the allowed-scheme set to that adapter rather than silently accepting arbitrary input.

Correct relative links from scraped pages

HTML commonly contains links such as /products/1 or ../login. Those paths are meaningful only in the context of the page that contained them. Resolve them against the page’s absolute URL before passing the result to Requests:

from urllib.parse import urljoin
import requests

page_url = "https://shop.example.com/catalog/index.html"
link_from_html = "/products/1"
absolute_url = urljoin(page_url, link_from_html)

print(absolute_url)  # https://shop.example.com/products/1
response = requests.get(absolute_url, timeout=30)

Also handle protocol-relative values such as //cdn.example.com/file.js with an absolute base. If your scraper receives a relative link but has no trustworthy page URL, stop and record the source instead of guessing a host.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Keep query parameters separate from the base URL

Requests’ params argument is useful for query strings, but it cannot add a missing scheme to the base URL:

import requests

response = requests.get(
    "https://api.example.com/search",
    params={"q": "python requests", "page": 1},
    timeout=30,
)
print(response.url)
# https://api.example.com/search?q=python+requests&page=1

This still fails because the base value is incomplete:

requests.get("api.example.com/search", params={"q": "python"})

Change the base to https://api.example.com/search; putting a protocol-looking string in a parameter does not change URL parsing.

Check proxy configuration independently

In Requests 2.x, proxy addresses also need a scheme. A proxy written as 10.10.1.10:3128 can produce MissingSchema; write it as http://10.10.1.10:3128 instead.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Proxy dictionary in code

import requests

proxies = {
    "http": "http://10.10.1.10:3128",
    "https": "http://10.10.1.10:3128",
}

response = requests.get(
    "https://example.com",
    proxies=proxies,
    timeout=30,
)
print(response.status_code)

The proxy protocol describes how the client connects to the proxy. It can be http:// even when the destination is an HTTPS URL, depending on your proxy setup.

Proxy environment variables

Requests can read proxy settings from environment variables. Inspect them when a request works on one machine but fails on another:

import os

for name in ("HTTP_PROXY", "HTTPS_PROXY", "http_proxy", "https_proxy"):
    print(name, repr(os.environ.get(name)))

Set each configured proxy to a complete value, for example:

HTTPS_PROXY=http://10.10.1.10:3128

Do not confuse a malformed proxy with a malformed destination. Log both values, and test the destination without a proxy only when your network policy permits it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Common causes and precise fixes

Symptom Likely cause Fix
Invalid URL ... No scheme supplied Domain, relative path, empty value, or None Inspect repr(url), then construct and validate an absolute URL.
Error appears only in a server or CI job Environment variable or configuration is missing Print the variable name and type (not credentials), then fail with a clear configuration error.
Error appears only behind a corporate network Proxy value lacks http:// or another required scheme Correct the proxy dictionary or environment variable.
InvalidURL: No host supplied Scheme exists but the host is absent or malformed Check the authority portion, such as https://example.com.
Adding params changes nothing Parameters do not repair the base URL Fix the first argument to requests.get() or the session request method.

Make the fix durable in application code

Fail early at configuration boundaries

Validate URLs when reading settings, not after a worker has started processing jobs:

import os
from urllib.parse import urlparse


def configured_url(name):
    raw = os.environ.get(name)
    if not isinstance(raw, str) or not raw.strip():
        raise RuntimeError(f"{name} is missing")
    value = raw.strip()
    parsed = urlparse(value)
    if parsed.scheme not in {"http", "https"} or not parsed.netloc:
        raise RuntimeError(f"{name} must be an absolute HTTP(S) URL")
    return value

API_BASE = configured_url("API_BASE_URL")

Use explicit timeouts after URL validation

A timeout does not fix MissingSchema, because that exception occurs before a network connection. It does prevent a valid URL from hanging indefinitely after the parsing problem is resolved:

import requests

session = requests.Session()
response = session.get(
    "https://api.example.com/health",
    timeout=(5, 30),  # connect timeout, read timeout
)
response.raise_for_status()

Log safely

Log the scheme, host, and source of a URL while redacting credentials and sensitive query values. Never write authorization tokens or cookies to application logs merely to diagnose this exception.

Cross-check the endpoint outside Python

Once you have an absolute URL, testing it with another client can separate URL construction from Python-specific code. The following commands still require a complete URL:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -I https://example.com

In Node.js, the built-in URL parser makes the same requirement visible:

const target = new URL('https://example.com');
const response = await fetch(target);
console.log(response.status);

If these clients work while your Python call raises MissingSchema, print the Python variable again; the two programs are probably not receiving the same value.

Troubleshooting checklist

  1. Copy the exact exception text and identify whether it says “No scheme supplied” or “No host supplied.”
  2. Print repr(url) and type(url).__name__ immediately before the request.
  3. Confirm the destination starts with the intended http:// or https://.
  4. If the value came from HTML, resolve relative links against the page URL.
  5. If it came from configuration, verify the variable exists in the failing process, container, or CI job.
  6. Inspect HTTP_PROXY, HTTPS_PROXY, and proxy dictionaries for a missing scheme.
  7. Keep query data in params, but repair the base URL separately.
  8. After parsing succeeds, add an explicit timeout and handle ordinary HTTP errors with raise_for_status().
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If the reason you are making this request is to obtain a website screenshot rather than an API response, ScreenshotNeo provides a direct HTTP endpoint instead of requiring you to install and configure a browser. It accepts the URL as a query parameter and returns an image or PDF. Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page and billing result in headers. Its MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf.

Use the same URL discipline that prevents MissingSchema: include https:// in the target URL.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for all parameters. You can also call it from Python:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

There is a free allowance of 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots, and every feature is available on every plan. Create a free ScreenshotNeo account.

FAQ

Does MissingSchema mean the website is offline?

No. Requests normally raises it while preparing the URL, before it attempts the network connection. Correct the address first, then investigate connectivity or HTTP status errors separately.

Can I solve it by adding a slash to the URL?

No. A trailing slash changes the path; it does not add a missing scheme. The value must begin with the protocol required by the destination.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why does the same code work locally but fail in production?

The production process may receive a different environment variable, scraped value, or proxy setting. Compare the redacted runtime value, its type, and proxy configuration in both environments.

Is http:// always interchangeable with https://?

No. Use the protocol supported and intended by the target. HTTPS is encrypted; an HTTP-only internal service may require HTTP.

Frequently Asked Questions

Can MissingSchema be caused by a proxy?

Yes. In Requests 2.x, a proxy address such as 10.10.1.10:3128 also lacks a scheme; configure it as http://10.10.1.10:3128 or the protocol required by your proxy.

What is the difference between MissingSchema and InvalidURL?

MissingSchema indicates that no URL scheme was parsed. InvalidURL with “No host supplied” indicates that a scheme exists but the host portion is absent or malformed.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.