# Access-Control-Expose-Headers Header — Values & Examples

> Lists the response headers that JavaScript on another origin is allowed to read.

A cross-origin fetch can only read seven CORS-safelisted response headers: `Cache-Control`, `Content-Language`, `Content-Length`, `Content-Type`, `Expires`, `Last-Modified` and `Pragma`. Everything else — `Content-Disposition`, `ETag`, `Retry-After`, `X-Total-Count` — reads as `null` in JavaScript, even though DevTools shows it. Listing a header here exposes it.

- Type: Response header
- Category: CORS
- Defined in: [Fetch Standard — CORS protocol](https://fetch.spec.whatwg.org/#http-cors-protocol)

## Syntax

```http
Access-Control-Expose-Headers: <header-name>, <header-name>…
```

## Examples

```http
Access-Control-Expose-Headers: Content-Disposition, ETag, X-Total-Count
```

download names, versions and pagination totals

```http
Access-Control-Expose-Headers: *
```

every header — only for requests without credentials

## Good to know

- It belongs on the actual response, not the preflight.
- With credentialed requests, `*` exposes nothing extra — list the names.
- If `response.headers.get("X-Request-Id")` returns null but DevTools shows the header, this is what's missing.

## How to set Access-Control-Expose-Headers

### Express

```
res.set("Access-Control-Expose-Headers", "Content-Disposition, ETag, X-Total-Count");
```

### Next.js (next.config.js)

```
module.exports = {
  async headers() {
    return [
      {
        source: "/(.*)",
        headers: [{ key: "Access-Control-Expose-Headers", value: "Content-Disposition, ETag, X-Total-Count" }],
      },
    ];
  },
};
```

### nginx

```
add_header Access-Control-Expose-Headers "Content-Disposition, ETag, X-Total-Count" always;
```

### Apache (.htaccess)

```
Header always set Access-Control-Expose-Headers "Content-Disposition, ETag, X-Total-Count"
```

## Check it

Fetch only the response headers and filter for Access-Control-Expose-Headers. In the browser, it's under Response Headers in DevTools → Network.

```sh
curl -sI https://example.com/ | grep -i '^access-control-expose-headers:'
```

## FAQ

### Why does response.headers.get() return null when DevTools shows the header?

DevTools shows everything the server sent. JavaScript on another origin only sees the safelisted headers plus those named in Access-Control-Expose-Headers.

## Related headers

- [Access-Control-Allow-Origin](https://www.devkult.com/headers/access-control-allow-origin.md): Tells the browser which origin may read this response from JavaScript running on another site.
- [Access-Control-Allow-Headers](https://www.devkult.com/headers/access-control-allow-headers.md): Lists the request headers a cross-origin request may include, in the response to a CORS preflight.
- [Content-Disposition](https://www.devkult.com/headers/content-disposition.md): Tells the browser to display a response inline or download it as a file, and with what file name.
- [Retry-After](https://www.devkult.com/headers/retry-after.md): How long the client should wait before retrying — sent with 429, 503 and some redirects.

## Further reading

- [CORS errors explained](https://www.devkult.com/blog/cors-errors-explained.md)

Open the interactive page: https://www.devkult.com/headers/access-control-expose-headers