# How to Fix CORS Errors When Fetching External APIs Using Python Requests

> Fix CORS errors when fetching external APIs using Python Requests. Implement a server-side proxy to bypass browser restrictions and successfully retrieve data.

- Repository: [Python Software Foundation/requests](https://github.com/psf/requests)
- Tags: how-to-guide
- Published: 2026-02-16

---

**You can fix CORS errors by implementing a server-side proxy with Python's `requests` library, which bypasses browser CORS restrictions entirely because it operates outside the browser's security sandbox.**

When building web applications that consume third-party APIs, developers frequently encounter Cross-Origin Resource Sharing (CORS) errors that prevent frontend JavaScript from reading API responses. This guide demonstrates how to fix CORS errors using the `psf/requests` library, leveraging the fact that server-side HTTP clients are not subject to browser-enforced CORS policies.

## Understanding Why CORS Errors Occur in Browsers

CORS is a browser-enforced security mechanism that prevents web pages from making requests to a different domain than the one serving the web page. When a browser sends a cross-origin request, it includes an `Origin` header, and if the server does not respond with appropriate `Access-Control-Allow-Origin` headers, the browser blocks the response from reaching your JavaScript code.

## Why Server-Side Python Requests Bypass CORS Restrictions

Unlike browsers, Python's `requests` library operates as a standalone HTTP client without a same-origin policy sandbox. When you use `requests` to fetch data from an external API, the TCP connection occurs directly between your server and the target API, eliminating the browser from the security chain entirely.

### The requests.api.get Implementation

The `get` function in [`src/requests/api.py`](https://github.com/psf/requests/blob/main/src/requests/api.py) provides the primary interface for making GET requests. As implemented in lines 62-74, this function delegates to the core `request` method:

```python

# src/requests/api.py – GET helper (lines 62-74)

def get(url, params=None, **kwargs):
    """
    Sends a GET request.
    """
    return request("get", url, params=params, **kwargs)

```

This convenience wrapper ultimately instantiates a `Session` object and calls its `request` method, which handles the actual HTTP transmission without browser intervention.

### How Session.request Handles HTTP Connections

In [`src/requests/sessions.py`](https://github.com/psf/requests/blob/main/src/requests/sessions.py), the `Session.request` method constructs a `PreparedRequest` object and dispatches it through an HTTP adapter. This process involves direct socket communication with the target server, completely bypassing any browser security context that would enforce CORS policies.

## How to Fix CORS Errors Using a Server-Side Proxy

The most reliable method to fix CORS errors when you cannot modify the external API is to create a server-side proxy endpoint. Your frontend calls your own backend, which then uses `requests` to fetch the external data and returns it with appropriate CORS headers.

### Complete Flask Proxy Implementation

Here is a production-ready Flask proxy that uses `requests` to bypass CORS restrictions while adding proper security controls:

```python

# app.py – a minimal Flask proxy

from flask import Flask, request, jsonify, Response
import requests

app = Flask(__name__)

# Allow browsers to call this endpoint from any origin.

@app.after_request
def add_cors_headers(resp: Response) -> Response:
    resp.headers["Access-Control-Allow-Origin"] = "*"
    resp.headers["Access-Control-Allow-Methods"] = "GET,POST,OPTIONS"
    resp.headers["Access-Control-Allow-Headers"] = "Content-Type,Authorization"
    return resp

@app.route("/proxy")
def proxy():
    external_url = request.args.get("url")
    if not external_url:
        return jsonify({"error": "Missing 'url' parameter"}), 400

    # Forward the request to the external API using `requests`.

    # The library handles redirects, TLS verification, etc.

    external_resp = requests.get(external_url, timeout=10)

    # Build a Flask response preserving status code and content.

    return Response(
        response=external_resp.content,
        status=external_resp.status_code,
        headers=dict(external_resp.headers),
        mimetype=external_resp.headers.get("Content-Type", "application/octet-stream")
    )

if __name__ == "__main__":
    app.run(debug=True)

```

This implementation leverages `requests.get` from [`src/requests/api.py`](https://github.com/psf/requests/blob/main/src/requests/api.py) to fetch external data without triggering browser CORS checks, then explicitly adds CORS headers to the response returned to the browser.

### Security Considerations for Production Proxies

When deploying a CORS proxy in production, implement these safeguards:

- **URL Validation**: Restrict the `url` parameter to specific allowed domains using an allowlist to prevent open proxy abuse.
- **Authentication**: Store API keys server-side in environment variables rather than exposing them in client-side code.
- **Rate Limiting**: Implement request throttling to prevent abuse and manage external API quota limits.
- **Error Handling**: Translate network timeouts and connection errors into appropriate HTTP status codes (502, 504) for the frontend.
- **Caching**: Add `Cache-Control` headers to store responses when external data is cacheable, reducing redundant API calls.

## Alternative Approaches to Fix CORS Errors

While the server-side proxy is the most robust solution, other methods exist depending on your constraints.

### Configuring the External API

If you control the external API or can contact its administrator, add the appropriate CORS headers to the server configuration:

```

Access-Control-Allow-Origin: https://yourdomain.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type

```

This approach eliminates the need for a proxy by allowing the browser to communicate directly with the API.

### Development-Only Workarounds

For local development only, you can temporarily disable CORS checks:

- **Browser Extensions**: Install extensions like "CORS Unblock" or "Allow CORS" to disable security checks in your development browser.
- **Browser Flags**: Launch Chrome with `--disable-web-security` or `--disable-site-isolation-trials` (highly insecure, use only for isolated testing).

**Never use these methods in production**, as they disable critical security protections.

## Summary

- **CORS is browser-only**: The security policy applies only to JavaScript running in web browsers, not to server-side HTTP clients.
- **Use `requests` as a proxy**: The `psf/requests` library bypasses CORS restrictions because it operates outside the browser sandbox, making it ideal for creating proxy endpoints.
- **Implementation location**: The `get` function in [`src/requests/api.py`](https://github.com/psf/requests/blob/main/src/requests/api.py) (lines 62-74) and the `Session` class in [`src/requests/sessions.py`](https://github.com/psf/requests/blob/main/src/requests/sessions.py) handle the actual HTTP transmission.
- **Security first**: Always validate URLs, hide API keys server-side, implement rate limiting, and add proper CORS headers to your proxy responses when fixing CORS errors in production applications.

## Frequently Asked Questions

### Why does Python requests not trigger CORS errors?

Python's `requests` library executes as a standalone HTTP client on your server, not within a browser's security sandbox. CORS policies are enforced exclusively by web browsers to protect users from malicious cross-origin requests. Since `requests` in [`src/requests/api.py`](https://github.com/psf/requests/blob/main/src/requests/api.py) creates direct TCP connections without sending an `Origin` header or checking `Access-Control-Allow-Origin` responses, it completely bypasses CORS restrictions.

### What is the most secure way to fix CORS errors when calling external APIs?

The most secure approach is implementing a server-side proxy using `requests` with strict URL validation and authentication controls. Store all API keys in server environment variables rather than client-side code, maintain an allowlist of permitted external domains to prevent open proxy abuse, and implement rate limiting to protect against abuse. This method fixes CORS errors while keeping sensitive credentials and network logic protected on the server.

### Can I use requests to bypass CORS in a client-side JavaScript application?

No, you cannot use Python `requests` directly in client-side JavaScript because it is a Python library requiring a Python runtime environment. However, you can deploy a Python backend that uses `requests` to fetch data from external APIs, then expose that data through your own API endpoints with proper CORS headers. Your JavaScript application calls your backend (same-origin or with permitted CORS), which then uses `requests` to retrieve the external data, effectively bypassing the external API's CORS restrictions.

### How do I handle authentication when proxying external APIs with Flask?

When building a Flask proxy to fix CORS errors, store API keys and authentication tokens in environment variables or secure configuration files on your server, never in client-side code or URL parameters. In your Flask route, retrieve these credentials from `os.environ` and inject them into the `requests` call via headers or query parameters as required by the external API. For example, use `requests.get(external_url, headers={"Authorization": f"Bearer {API_KEY}"}, timeout=10)` where `API_KEY` is loaded server-side. This keeps sensitive credentials secure while allowing your proxy to authenticate with the external service.