Skip to main content
Run bunny skills install --global so AI coding agents, such as Claude Code, Cursor, and Codex, can run this migration for you. Then ask your agent: “Migrate my Mux videos to Bunny Stream.”
bunny stream import is in Public Preview and still in development. Commands, flags, and output may change, so what you see can differ from the examples in this guide. To report a bug, open an issue on the Bunny CLI repository.
Bunny Stream bills only for the storage and bandwidth you use. See the Bunny Stream pricing page for current rates.

Overview

Diagram of the Bunny CLI listing Mux assets and Bunny Stream fetching each file directly from Mux
The Bunny CLI lists every ready video in your Mux environment and hands each one to Bunny Stream, which fetches the file directly from Mux. Nothing is downloaded to your machine. Each imported video is tagged with its Mux asset ID under the muxAssetId metatag, so running the import again skips videos that are already imported.

Scope

The import copies the video files and their titles. Settings that control how and where videos play stay on Mux, so plan to set up their Bunny equivalents.
Signed playback policies are not migrated. Every imported video follows the security settings of its Bunny library, and a new library allows playback from any site. Assets with a signed playback policy on Mux are imported through their master file, but on Bunny they play for anyone with the URL until you protect the library. Before you publish the new URLs, set up Allowed domains, and turn on embed view token authentication or CDN token authentication if you signed your Mux playback URLs.

Prerequisites

Migrate your videos

1

Install and authenticate the Bunny CLI

Install the Bunny CLI with the shell installer or npm:
The installer downloads a prebuilt binary for your platform and places it on your PATH.
See Installation for more options. Then authenticate the CLI with your bunny.net account:
bunny login opens your browser to complete authentication and stores the credentials locally. The first time you log in from an interactive terminal, it also offers to install the agent skill for AI coding tools. On a remote machine or in CI without a browser, run bunny login --api-key "$BUNNYNET_API_KEY" instead, with a key from Account Settings > API key.
2

Create a Bunny Stream library

Create a library for the imported videos, or skip this step to use an existing one:
DE is always the main storage region. Replicate to the regions closest to your audience, from UK, SE, NY, LA, SG, SYD, BR, and JH. You can’t remove a replication region later.
Set encoding options, such as --resolutions or --encoding-tier, when you create the library. Changes you make later apply only to new uploads, not to videos that are already imported. Run bunny stream libraries create --help to see every option, or read Encoding.
When the CLI asks how to add videos, choose Later. You start the import in the next steps.Copy the library ID from the output. You pass it to --library in the import commands. The flag also accepts the library’s name, and --lib works as a short alias.
3

Create a Mux access token

The Bunny CLI needs a Mux Token ID and Secret Key to list your videos and look up their download URLs.Open Settings > Access Tokens in the Mux dashboard and click Create Token.
The Access Tokens page in the Mux dashboard with the Create token button
Access tokens are scoped to a Mux environment, so first select the environment that holds the videos you want to migrate. If you have videos in more than one environment, see Migrate more than one Mux environment. Enter a token name, such as migrate-to-bunny, and give it the Mux Video permission with both Read and Write access. The Bunny CLI only needs Read. Write is for the helper script in the next step, which turns on master access for your assets.
The new access token form in Mux with the Mux Video Read and Write permissions selected
Copy the Token ID and the Secret Key. Mux shows the Secret Key only once.
The Save token dialog in Mux showing the Token ID and Secret Key
4

Make your Mux videos downloadable

Bunny imports a video by fetching a file from a URL. Mux stores your videos for streaming, so a downloadable file exists only when one of the following is true:
  • Master access is enabled: Mux prepares a temporary copy of the original upload. The CLI prefers this file because it is the highest quality version of the video, and it also works for videos with signed playback IDs. The master URL expires 24 hours after Mux makes it ready.
  • Static MP4 renditions are ready on a public playback ID: the CLI picks the first one available in this order: highest.mp4, capped-1080p.mp4, then the resolution renditions from 2160p.mp4 down. Renditions on signed playback IDs cannot be used, as Bunny cannot supply the signed token those URLs require.
If your assets already have static MP4 renditions on public playback IDs, skip to the next step.Otherwise, enable master access on every asset right before you migrate. The following Python script does that through the Mux API. It prompts for your Token ID and Secret Key, requests master access for every ready asset, and waits until Mux has prepared each master file. Save it as enable_mux_masters.py:
enable_mux_masters.py
Run it and enter your Token ID and Secret Key when prompted:
The script reports its progress and finishes once every master file is ready:
Bunny must fetch each master file within 24 hours of Mux making it ready. On a large library, run the next two steps as soon as the script finishes, and add --concurrency 10 (up to 20) to the import so the CLI hands videos to Bunny faster than the default of three at a time.
5

Preview the migration with a dry run

Run the import with --dry-run, using the library ID from step 2:
--dry-run prints the import plan without making any changes to either platform.The CLI then prompts for your Mux credentials. Enter the Token ID at the Token ID prompt and the Secret Key at the Token Secret prompt:
Once Mux accepts them, the CLI offers to save them so later runs skip these prompts. Press Enter to accept:
The CLI stores saved credentials in ~/.config/bunnynet/stream-import-credentials.json (or under $XDG_CONFIG_HOME/bunnynet/ when it is set). Only your user account can read the file, and it is separate from the main Bunny CLI config. Saved credentials belong to the active Bunny CLI profile. If Mux later rejects them, for example after you revoke the token, the CLI deletes them and prompts again on the next run. If you answer no, the CLI prompts on every run.The MUX_TOKEN_ID and MUX_TOKEN_SECRET environment variables always take priority over saved credentials.
The dry run then prints a summary and the import plan:
Already imported counts videos that are already in the library, and To import counts the ones a real run would import. Mux’s asset list does not report file sizes, so the summary has no Size row.Every video is listed under (no collection), since Mux has no folders. A video without a title on Mux is listed under its asset ID and keeps that ID as its title on Bunny. You can rename it in the dashboard after the import.The dry run does not check whether each asset has a downloadable file. An asset with no ready master file or public static MP4 rendition still appears in the plan, then fails during the import.
6

Run the import

Run the same command without --dry-run:
The CLI prints the same summary, then asks for confirmation. Type y and press Enter to start:
The CLI skips videos that are already imported, hands the rest to Bunny three at a time, and tags each one with muxAssetId. It returns once every video is queued. Bunny then fetches each file directly from Mux and encodes it.
The import command also accepts these flags:
  • --wait keeps the command running, with a live encoding progress indicator, until Bunny has encoded every video.
  • --force skips the confirmation prompt and the offer to retry failed videos, for unattended or CI runs.
  • --concurrency N sets how many videos the CLI passes to Bunny in parallel, from 1 to 20.
  • --clean-failed deletes the failed Bunny copies of videos before importing them again, including videos that Bunny rejected.
  • --retry-stalled deletes and imports again any video stuck at zero bytes on Bunny.
  • --request-timeout sets how many seconds one request to Mux or Bunny can take before it gives up (default 30).
  • --video-timeout sets how many seconds the hand-off of one video to Bunny, or with --wait its encoding, can take before it gives up (default 5400).
Run bunny stream import --help for the full list.
7

Watch encoding progress

The import returns before Bunny finishes encoding. Check progress with the status command:
It prints one row per queued video, with its status on Bunny, encode percentage, size, and when it was queued:
Run it again until the last line reports 0 processing. The command exits with a non-zero code when any video has failed, so you can also use it as a check in scripts.
8

Verify in the bunny.net dashboard

Open the bunny.net dashboard and go to Stream > Your library > Manage library to confirm every video has encoded.
The Manage library page in the bunny.net dashboard listing the imported videos
Set up the library’s security settings if you have not already, then replace the Mux playback URLs (stream.mux.com) and Mux Player references in your site with their Bunny Stream equivalents. See Embedding videos for the embed and player options.

Troubleshooting

When videos fail during an interactive import, the CLI lists each failure and offers to retry them:
Answer y to retry them in the same run. If the import was interrupted, or you declined the retry, run it again with --resume:
--resume retries failed videos, processes any that were still outstanding, and re-applies the muxAssetId tag to videos Bunny fetched before the run stopped. It stops retrying a video after three failed attempts and skips videos that Bunny rejected. To retry those too, add --clean-failed, which deletes their Bunny copies first.Running the import again is always safe. Videos that already carry the muxAssetId tag are skipped, and the CLI reports Everything is already imported once nothing is left.
The video had neither a ready master file nor a usable static MP4 rendition when the CLI looked it up. This happens when you skipped step 4, when a master file was still preparing, or when more than 24 hours have passed since the master files became ready.Decline the retry prompt, run the script from step 4 again, then run the import again without --resume. Requesting master access again gives each expired master file a fresh URL, and a plain run retries every video that is not yet in the library. Repeat until the import reports that everything is already imported.For very large libraries, static MP4 renditions on public playback IDs avoid the 24-hour window, since they do not expire. Check Mux’s pricing for static renditions before you enable them.
A 401 means the Token ID or Secret Key is wrong. A 403 on a master-access request means the token is missing the Write permission from step 3.If the script reports that Mux could not prepare a master file for an asset, the import can still use a static MP4 rendition on a public playback ID. Otherwise, that asset fails with No download available.
If bunny stream import status reports videos stuck at zero bytes, run the import again with --retry-stalled to delete and fetch them again.

Migrate more than one Mux environment

Mux access tokens are scoped to a single environment, such as Production or Development. To migrate several environments, repeat steps 2 to 8 for each one, with a token created in that environment. Import each environment into its own Bunny library. The CLI keeps one saved import per source and library, so a separate library keeps each environment’s progress, --resume, and status apart, and keeps test videos out of your production library. The CLI saves one set of Mux credentials per Bunny CLI profile, and uses it without prompting for the next environment. Point the CLI at the next environment’s token in one of these ways:
  • Set MUX_TOKEN_ID and MUX_TOKEN_SECRET in your shell. Environment variables always take priority over saved credentials.
  • Run the import with a different Bunny CLI profile, using --profile.
Last modified on November 5, 2026