Cloudflare
Serve video files from R2 through a Cloudflare custom domain.
Serve the video files Chunkify writes to R2 through a custom domain such as https://media.example.com. Cloudflare delivers the files and caches media segments close to your viewers.
Start with a Cloudflare R2 storage connection and a domain in the same Cloudflare account as the bucket. Replace media.example.com and https://app.example.com below with your own values.
If you connected R2 with Set up with Cloudflare in Chunkify, the guided setup already attaches your playback domain, adds segment caching, and configures browser access.
Continue with Keep playlists fresh to configure playlist caching, then Verify playback.
Connect a playback domain
In Cloudflare, open R2 → Overview, select your bucket, then open Settings.
- Under Custom Domains, select Add.
- Enter a playback hostname, such as
media.example.com, and select Continue. - Review the DNS record, then select Connect Domain.
- Wait for the domain status to become Active before testing HTTPS delivery.
Use the R2 custom domain connection rather than a CNAME to an r2.dev URL. Cloudflare reserves r2.dev for development traffic.
Connecting a custom domain makes the bucket's objects publicly readable at their URLs, including any source videos stored there. Keep private sources in a separate bucket if needed.
The domain root must map to the bucket root. Keep the output prefix in the URL. Do not add a rewrite that removes it or adds it a second time.
Allow playback from your website
The R2 bucket's CORS policy also supplies the headers for its custom domain. In the bucket's Settings → CORS policy, merge this playback rule with any existing rules:
[
{
"AllowedOrigins": ["https://app.example.com", "https://chunkify.dev"],
"AllowedMethods": ["GET", "HEAD"],
"AllowedHeaders": ["Range"],
"ExposeHeaders": ["Accept-Ranges", "Content-Length", "Content-Range", "ETag"],
"MaxAgeSeconds": 3600
}
]
Replace the application origin with your website's origin. Keep https://chunkify.dev for playback in the Chunkify dashboard. The rule allows playback reads and byte-range requests.
Preserve existing upload rules when saving the complete policy. Browser uploads go directly to R2 and also need PUT, the Content-Type request header, and an exposed ETag. See Configure CORS.
After changing CORS, purge previously cached files so their old response headers do not persist. Cloudflare's R2 CORS guide explains this behavior.
Configure caching
Chunkify writes HLS playlists with Cache-Control: no-cache because they can change as renditions and captions become available. Completed media segments have a long cache lifetime.
Cloudflare caches .mp4 files by default, including HLS initialization files. Its default file extensions do not include .m4s segments or .m3u8 playlists.
Cache video segments
Select the domain's website in Cloudflare, then open Caching → Cache Rules → Create rule. Name the rule Chunkify video segments and choose Custom filter expression.
Use Edit expression to enter this filter:
(http.host eq "media.example.com" and ends_with(http.request.uri.path, ".m4s"))
Set the following options, then deploy the rule:
| Setting | Value |
|---|---|
| Cache eligibility | Eligible for cache |
| Edge TTL | Follow the response's Cache-Control header; bypass cache if it is missing |
| Browser TTL | Respect origin |
Keep the origin's cache lifetimes. A fixed TTL override can retain responses longer than Chunkify intends. See Cloudflare's cache rule settings.
Keep playlists fresh
Create a second rule named Chunkify HLS playlists with this filter:
(http.host eq "media.example.com" and ends_with(http.request.uri.path, ".m3u8"))
Set Cache eligibility to Bypass cache, then deploy. Avoid rules that force a browser cache lifetime for playlists so the browser honors Chunkify's no-cache header.
Place these rules after broader rules that affect the playback hostname. Cloudflare applies matching rules in order, and the last value for a setting wins.
Add the CDN domain to Chunkify
In your Project, open Project settings → Storage, edit the R2 connection, and set CDN base URL to the custom domain's HTTPS origin:
https://media.example.com
Enter only the HTTPS origin, without an output prefix, path, or query string, then select Save changes. The guided Cloudflare setup fills in this field for you.
For example, an object stored at chunkify/asset_2G6MJiNz71bHQGNzGwKx5cJwPFS/manifest.m3u8 is served at:
https://media.example.com/chunkify/asset_2G6MJiNz71bHQGNzGwKx5cJwPFS/manifest.m3u8
Chunkify returns this address as the video asset's cdn_url. Adding the base URL does not verify delivery. See CDN delivery for how playback URLs are built.
Verify playback
Create a test video asset using this storage connection. Once playback is available, use its cdn_url in a player on your website and check the browser's Network panel:
- The master playlist, rendition playlists, and media requests succeed, and the video plays and seeks.
- Responses allow your website's origin through
Access-Control-Allow-Origin. - The poster, timeline previews, and any captions load.
- Byte-range media requests return
206 Partial Contentwhen requested. - After additional HLS renditions or caption tracks are ready, a new master-playlist request reflects the available outputs.
- Repeated media-segment requests can return
CF-Cache-Status: HIT, indicating a cache hit.
To inspect a playlist's response headers, include your website's origin. Replace the example path with a real video asset's path:
curl --silent --show-error \
--dump-header - \
--output /dev/null \
--header 'Origin: https://app.example.com' \
'https://media.example.com/chunkify/asset_2G6MJiNz71bHQGNzGwKx5cJwPFS/manifest.m3u8'
Test playback from your website as well as the Chunkify dashboard. A successful request without an Origin header does not establish that browser CORS works.
Troubleshoot delivery
| Symptom | Check |
|---|---|
A file returns 404 |
Confirm the exact object key in R2 and keep the output prefix in the URL. Test a real object URL; the domain root does not list files. If the file now exists, purge a previously cached 404. |
| Browser reports a CORS error | Check the requesting website's origin in the bucket's CORS policy, then purge old cached responses. |
| Playback shows outdated renditions or captions | Check the playlist bypass rule and any later cache rules that override it. |
| Player receives an HTML challenge | Review Cloudflare security rules on the playback hostname. Media requests must receive the requested file. |