Skip to content

CORS Headers Reference — Complete Guide to Access-Control-* Headers

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about CORS Headers Reference. We cover key concepts, practical examples, and best practices to help you master this topic.

The CORS protocol uses seven response headers and two request headers, each serving a specific role in the browser-server permission negotiation for cross-origin resource access.

What You'll Learn

  • The purpose of every Access-Control-* header
  • How request and response headers interact
  • How to configure each header correctly

Why It Matters

Misconfiguring any CORS header can block legitimate requests or create security vulnerabilities. DodaTech's API Gateway uses these headers to enable secure cross-origin communication between Doda Browser extensions and backend services.

flowchart TD
    subgraph "Request Headers"
        OH["Origin"]
        RM["Access-Control-Request-Method"]
        RH["Access-Control-Request-Headers"]
    end
    subgraph "Response Headers"
        AO["Access-Control-Allow-Origin"]
        AM["Access-Control-Allow-Methods"]
        AH["Access-Control-Allow-Headers"]
        EH["Access-Control-Expose-Headers"]
        AC["Access-Control-Allow-Credentials"]
        MA["Access-Control-Max-Age"]
    end
    Browser --> OH
    Browser --> RM
    Browser --> RH
    AO --> Browser
    AM --> Browser
    AH --> Browser
    EH --> Browser
    AC --> Browser
    MA --> Browser

Code Examples

// JavaScript cannot read these headers directly
// But you can see them in the Network tab
// Here's how to check if CORS headers are present
fetch('https://api.example.com/data')
  .then(response => {
    // These are CORS-safe listed headers only
    console.log('Content-Type:', response.headers.get('content-type'));
    // Custom headers need Access-Control-Expose-Headers
  });
# Setting all CORS headers in a Flask response
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/api/data')
def get_data():
    response = jsonify({"message": "success"})
    response.headers['Access-Control-Allow-Origin'] = 'https://app.example.com'
    response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE'
    response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
    response.headers['Access-Control-Expose-Headers'] = 'X-RateLimit-Remaining'
    response.headers['Access-Control-Allow-Credentials'] = 'true'
    response.headers['Access-Control-Max-Age'] = '86400'
    return response
# Inspect all CORS headers in a response
curl -I -H "Origin: https://app.example.com" \
  https://api.example.com/data 2>&1 | grep -i "access-control"

# Sample output:
# access-control-allow-origin: https://app.example.com
# access-control-allow-methods: GET, POST
# access-control-allow-credentials: true
# access-control-max-age: 86400

Common Mistakes

1. Setting Allow-Origin to * with Credentials

The wildcard * cannot be used with Access-Control-Allow-Credentials: true.

2. Forgetting Access-Control-Expose-Headers

By default, only simple response headers are exposed to JavaScript. Custom headers need explicit exposure.

3. Overly Permissive Allow-Methods

Including methods your API does not support creates unnecessary surface area.

4. Omitting OPTIONS from Allow-Methods

Preflight requests use OPTIONS. It must be included in Allow-Methods for preflighted requests.

5. Setting Max-Age Too Low or Too High

Low values increase preflight requests; high values risk stale cached permissions.

Practice Questions

  1. What is the only required CORS response header?
  2. Which header controls what custom headers JavaScript can read from the response?
  3. What happens if Access-Control-Allow-Credentials is set to true but Allow-Origin is *?
  4. Which request header tells the server what custom headers the browser wants to send?
  5. What is the purpose of Access-Control-Max-Age?

Answers:

  1. Access-Control-Allow-Origin.
  2. Access-Control-Expose-Headers.
  3. The browser rejects the response. Wildcard and credentials cannot be used together.
  4. Access-Control-Request-Headers.
  5. It tells the browser how long to cache the preflight response.

Challenge: Create a reference table of all seven CORS response headers with example values, description, and browser behavior when each is missing or misconfigured.

FAQ

Can I use multiple values in Access-Control-Allow-Origin?

No. The value must be a single origin, or the wildcard *, or null. To support multiple origins, you must dynamically set the value based on the request Origin header.

What is the default value of Access-Control-Expose-Headers?

By default, only Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, and Pragma are exposed to JavaScript.

Is the Vary header important with CORS?

Yes. When using dynamic Access-Control-Allow-Origin, include Vary: Origin to prevent caching issues with proxy servers and CDNs.

Can I use Access-Control-Allow-Headers with *?

Yes. The wildcard * is allowed for Allow-Headers, Allow-Methods, and Expose-Headers in modern browsers, but not with credentials.

What does Access-Control-Request-Headers look like in a preflight?

It contains a comma-separated list of header names, lowercased, like: access-control-request-headers: content-type, authorization

Mini Project

Build an interactive CORS headers tester: a server with configurable CORS headers and a client page that displays which headers were received. Add sliders to toggle each header and see how the browser reacts. Include a log panel showing the exact headers exchanged.

What's Next

Deep dive into Access-Control-Allow-Origin behavior including wildcard and dynamic origins, then explore Access-Control-Allow-Methods in detail.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro