> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://fastpix.com/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://fastpix.com/docs/_mcp/server.

# Enable secure video playback

> Learn how to protect video content using token-based authentication in the FastPix Android Player.

Learn how to protect video content using token-based authentication in the FastPix Android Player.

## Set up token-based playback

Pass a `playbackToken` in your `setFastPixMediaItem` configuration to secure the stream:

```kotlin
private fun startPlayback() {
    player?.setFastPixMediaItem {
        playbackId = "YOUR_PLAYBACK_ID"
        playbackToken = "SET_PLAYBACK_TOKEN"
    }
}
```

A private video needs only its playback token, with the audience `"aud": "media:<playbackId>"`. It is not DRM, so do not set `drmConfig`. For DRM-protected streams, see [Play DRM-protected content](/docs/android-player/play-drm-protected-content) instead.

As a playlist entry, pass the token to `PlaylistItem.fastPix`:

```kotlin
PlaylistItem.fastPix("YOUR_PLAYBACK_ID", playbackToken = "SET_PLAYBACK_TOKEN")
```

> **Note:** Before SDK 2.2.2, setting a `playbackToken` without a `drmConfig` reported a false `onError` (code 9010, "Token is empty") even though the video played. Upgrade to 2.2.2 or later to clear it.

## Fetch tokens early and reuse them

A playback token is reusable until it expires (the JWT's `exp` claim), so fetch it before playback and keep it. Until the token arrives the player cannot start, cache or no cache.

* Fetch a video's token as soon as you know it may be played, for example when the course or feed loads or a card is tapped, not when the user presses play.
* Reuse a cached token until shortly before `exp`. Fetch a new one only when it is about to expire or the server rejects it (HTTP 401 or 403).
* Pre-cache private videos with the same playback ID and token: `preCacher.preCacheItems(listOf(PlaylistItem.fastPix(id, token)))`. The token is not part of the cache key, so a refreshed token for the same playback ID still starts from disk. See [Pre-cache videos before a player exists](/docs/android-player/pre-cache-videos).

## How tokens protect your content

* **Unique playback ID** identifies each video asset individually for secure and trackable playback.
* **Signed token authentication** grants access only if a valid, cryptographically signed token is present in the playback URL.
* **Time-limited access:** tokens can include expiration timestamps, allowing playback only within a defined time window.
* **User-specific control:** tokens can be generated per user or session, restricting access based on identity or device.
* **Prevents unauthorized sharing:** signed tokens stop others from reusing the URL, protecting content from piracy and hotlinking.
* **Customizable restrictions:** tokens can include rules like IP restrictions, usage limits, or geo-blocking.

## What's next

* [Use a custom domain](/docs/android-player/use-custom-domain) to stream from your own domain with token support.
* [Handle playback errors](/docs/android-player/handle-playback-errors) to troubleshoot token validation failures.