ffmpegauthorizationbearer-tokenapistreaming

How to Use FFmpeg Authorization Headers (Bearer Token Example)

·Javid Jamae·5 min read
How to Use FFmpeg Authorization Headers (Bearer Token Example)

You need to download or process a video that's behind authentication. Maybe it's an HLS stream from a CDN, a DASH manifest on a protected endpoint, or just a direct MP4 URL that requires a bearer token. FFmpeg can handle all of these, but the -headers syntax trips people up.

This post shows you the exact commands that work.

The Basic Syntax

FFmpeg's -headers flag lets you pass custom HTTP headers when fetching remote URLs. For bearer token auth, it looks like this:

ffmpeg -headers "Authorization: Bearer YOUR_TOKEN_HERE\r\n" -i https://example.com/protected/video.mp4 -c copy output.mp4

Two things to notice. First, the \r\n at the end is required. FFmpeg expects HTTP-style line endings after each header. Skip it and the header won't be sent correctly. Second, the entire header value goes in double quotes.

The -headers flag must come *before* the -i input flag. FFmpeg processes options left to right, so headers declared after the input URL won't be applied to that input.

Downloading a Protected HLS Stream

HLS streams are the most common use case. Your video player can handle the auth token in JavaScript, but you need FFmpeg to do the same thing server-side.

ffmpeg -headers "Authorization: Bearer eyJhbGciOiJIUzI1NiIs...\r\n" \
  -i https://cdn.example.com/stream/master.m3u8 \
  -c copy \
  -bsf:a aac_adtstoasc \
  output.mp4

FFmpeg applies the -headers to every HTTP request it makes for that input. So when it fetches the master playlist, then the variant playlists, then each .ts segment, the bearer token goes with every request. You don't need to handle segments individually.

The -bsf:a aac_adtstoasc bitstream filter is there because HLS segments often use ADTS-wrapped AAC audio, and MP4 containers need the raw AAC stream. Without it, you might get audio playback issues in some players.

Multiple Headers

Some APIs need more than just authorization. You can chain headers together with \r\n between them:

ffmpeg -headers "Authorization: Bearer YOUR_TOKEN\r\nX-Custom-Header: some-value\r\nUser-Agent: MyApp/1.0\r\n" \
  -i https://api.example.com/video/12345 \
  -c copy output.mp4

All headers go in a single -headers string, separated by \r\n. Don't use multiple -headers flags. FFmpeg only reads the last one, so your earlier headers would be silently ignored.

DASH Streams

DASH manifests work the same way. The headers apply to the .mpd file and all referenced audio and video segments:

ffmpeg -headers "Authorization: Bearer YOUR_TOKEN\r\n" \
  -i https://cdn.example.com/dash/manifest.mpd \
  -c copy \
  -movflags +faststart \
  output.mp4

The -movflags +faststart moves the MP4 metadata to the beginning of the file, which is useful if you plan to serve the output over HTTP. Players can start playback before the full download finishes.

Common Gotchas

Quoting issues in different shells. If you're on Windows with cmd.exe, single quotes don't work the way they do on Linux/macOS. Use double quotes and escape inner quotes:

# Linux/macOS - both work
ffmpeg -headers 'Authorization: Bearer MY_TOKEN\r\n' -i url -c copy out.mp4
ffmpeg -headers "Authorization: Bearer MY_TOKEN\r\n" -i url -c copy out.mp4

# Windows cmd - double quotes only
ffmpeg -headers "Authorization: Bearer MY_TOKEN\r\n" -i url -c copy out.mp4

# PowerShell - backtick escaping
ffmpeg -headers "Authorization: Bearer MY_TOKEN`r`n" -i url -c copy out.mp4

Token in a variable. When the token comes from an environment variable or script output:

TOKEN=$(curl -s https://auth.example.com/token | jq -r '.access_token')
ffmpeg -headers "Authorization: Bearer $TOKEN\r\n" \
  -i https://cdn.example.com/stream.m3u8 \
  -c copy output.mp4

The header isn't being sent. Run FFmpeg with -v debug to see the actual HTTP requests. Look for your header in the output:

ffmpeg -v debug -headers "Authorization: Bearer YOUR_TOKEN\r\n" \
  -i https://example.com/video.mp4 -c copy output.mp4 2>&1 | grep -i auth

If the header doesn't show up, the most likely cause is a missing \r\n at the end. The second most common issue is putting -headers after -i instead of before it.

Token expiration during long downloads. Bearer tokens expire. If you're downloading a long HLS stream with hundreds of segments, your token might expire partway through. FFmpeg won't refresh it. You'll see 401 or 403 errors in the output once the token dies.

For short clips, this isn't a problem. But for streams longer than your token's TTL, you need either a long-lived token or a wrapper script that re-authenticates and resumes.

Redirects can strip headers. Some CDNs redirect your initial request to a different domain. FFmpeg follows redirects by default, but it won't always forward your custom headers to the new domain. If your video is behind a CDN that does domain-level redirects, you might need to use the final URL directly.

When CLI Headers Get Painful

Managing tokens, handling expiration, dealing with shell quoting across different environments, and debugging redirect issues gets old fast. If you're building video processing into an application rather than running one-off commands, an API that handles authentication for you makes more sense.

FFmpeg Micro lets you pass source URLs with auth headers through a simple REST API. You send the URL and headers as JSON, and the service handles the FFmpeg execution, scaling, and error recovery. No shell quoting, no token refresh logic, no \r\n formatting.

{
  "input": {
    "url": "https://cdn.example.com/stream.m3u8",
    "headers": {
      "Authorization": "Bearer SOURCE_VIDEO_TOKEN"
    }
  },
  "output": {
    "format": "mp4"
  }
}

Just JSON. The kind of thing you can build in an afternoon and not think about again.

Ready to process videos at scale?

Start using FFmpeg Micro's simple API today. No infrastructure required.

Get Started Free