# Configure CORS

> Allow browser uploads and video playback from your application.

CORS determines whether a browser lets your website make cross-origin requests and read responses from your storage and CDN. It does not grant storage credentials or make files public. With customer-owned storage, configure it for each browser action you use: direct video uploads, playback, or both. A working storage connection does not prove either action works in a browser.

## Identify the browser origins

List the origins where people upload or watch your videos. An origin includes the scheme, hostname, and port if one is present, but no path: for example, `https://app.example.com` or `http://localhost:3000`.

Include `https://chunkify.dev` if you upload or play videos in the Chunkify dashboard. Add your production, staging, and local application origins as needed. Test each origin separately; success in the dashboard does not establish that your website can use the same files.

## Allow browser uploads

The Chunkify uploader sends a video directly from the browser to the selected storage with `PUT` and a `Content-Type` header. Allow that method and header from every origin that hosts the uploader. The browser may send an `OPTIONS` preflight first; for S3-style bucket policies, the provider handles that request using the configured `PUT` rule. Do not add `OPTIONS` to `AllowedMethods`.

For [multipart sessions](/docs/integration/video-upload#multipart-sessions-for-large-files), also expose the storage response's `ETag` header. A multipart-capable uploader needs the exact ETag from each successful part PUT to complete the upload. Add `ETag` to `ExposeHeaders` even when the bucket is used only for uploads.

This bucket rule is needed only for browser uploads to customer-owned storage. Creating a source from an existing object or a video URL does not upload a file from the browser. The upload completion endpoint has its own CORS handling; its settings do not replace bucket CORS.

## Allow video playback

When video files are served from another origin, allow the viewing website to request the HLS playlists, media segments, poster, timeline previews, and captions. Allow `GET` and `HEAD`, and permit the `Range` request header for players that request part of a media file. Expose `Accept-Ranges`, `Content-Length`, `Content-Range`, and `ETag` so browser code can inspect those responses when needed.

The browser needs these CORS headers on the response from the playback URL, usually your CDN domain. With an R2 custom domain, the bucket's CORS policy supplies them. With a separate CDN such as CloudFront, the CDN can pass through the bucket's CORS headers or add them itself. Test the CDN URL from the viewing website; a working bucket request does not prove playback works through the CDN.

## Apply a merged bucket policy

Read your bucket's current CORS policy before changing it. S3-style CORS updates replace the complete policy, so include any rules your other applications still need. This example uses the AWS S3 API and CLI shape and combines upload and playback access for the Chunkify dashboard and one website. Uploads use `PUT` and `Content-Type`; multipart uploads also need the exposed `ETag`. Playback uses `GET`, `HEAD`, `Range`, and the exposed response headers:

```json
{
  "CORSRules": [
    {
      "AllowedOrigins": ["https://chunkify.dev", "https://app.example.com"],
      "AllowedMethods": ["GET", "HEAD", "PUT"],
      "AllowedHeaders": ["Content-Type", "Range"],
      "ExposeHeaders": ["Accept-Ranges", "Content-Length", "Content-Range", "ETag"],
      "MaxAgeSeconds": 3600
    }
  ]
}
```

Replace the example origins with yours and merge this rule with the existing policy. If you do not use browser uploads, omit `PUT` and `Content-Type`. If uploads and playback happen on different websites, use separate rules so viewing-only origins are not allowed to make cross-origin `PUT` requests. The AWS S3 console accepts the `CORSRules` array without its outer object. Other providers may use a different format or console fields; apply the equivalent rule using their CORS settings. See the [Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ManageCorsUsing.html) and [Cloudflare R2](https://developers.cloudflare.com/r2/buckets/cors/) CORS documentation for provider syntax.

## Check the CDN edge

Confirm that the CDN returns CORS headers for your website's origin and supports the requests your player makes, including byte-range requests. It should preserve media `Content-Type` and range response headers. Check its cache rules too: a video asset's master playlist can change while processing continues.

## Test from each website

From each application origin, upload a small video if you use browser uploads, then play a video asset through its CDN URL. Check the poster and timeline previews as well as the stream. In browser developer tools, inspect failed preflight and media requests for the request origin, method, headers, and the response's CORS headers. A successful server-side upload or direct download does not verify browser access.
