CLI and desktop UI that download anime from Crunchyroll with Widevine DRM decryption, outputting MKV files with metadata, selectable audio dubs, and subtitles.
Built in Go. A temporary browser is used only for optional account sign-in; downloads fetch DASH manifests directly through authenticated Crunchyroll APIs, decrypt with Widevine CDM keys, and mux with FFmpeg.
- Download single episodes or entire seasons/series
- CLI and a simple cross-platform desktop UI (macOS, Linux, Windows)
- One-click Crunchyroll sign-in through an isolated Chrome, Edge, Brave, or Chromium window
- Paste a Crunchyroll URL in the UI to list episodes (or a single episode) and pick download options
- Convert a local video file, multiple dropped files, or a full folder to a selected video/audio quality
- Choose audio language (dub) and subtitle language per download
- Configurable video quality (1080p, 720p, etc.) and audio quality (192k, 128k, etc.)
- Widevine DRM decryption (
.wvdfile orclient_id.bin+private_key.pem) - MKV output with embedded metadata and filenames that include the Crunchyroll episode title (
Show S01E02 Episode Title [1080p].mkv) - Parallel segment downloads (10 workers) for faster throughput
- Retry with exponential backoff on connection errors
- Batch download from a text file of URLs
- Automatic access token refresh before expiry, with bounded retries on 401 responses
- Skips already-downloaded episodes (re-running a season scans the series folder and only fetches missing or incomplete files)
- After a season pass, retries missing or incomplete episodes
| Layer | Technology |
|---|---|
| Language | Go 1.25 |
| Desktop UI | Fyne v2 (OpenGL / native windowing) |
| DRM | gowidevine (Widevine CDM + PSSH extraction) |
| Manifest Parsing | go-mpd (DASH MPD) |
| Muxing | FFmpeg (external, must be installed) |
| Auth | Managed browser sign-in or etp_rt cookie |
| Output | MKV container with metadata |
crunchyroll-downloader/
├── .github/
│ └── workflows/
│ └── build.yml # CI: cross-platform build + GitHub Release
├── assets/ # Default location for .wvd / client_id.bin / private_key.pem
├── bin/ # Local build output (gitignored)
├── main.go # CLI flags, URL routing, audio language GUID resolution
├── gui.go # Desktop UI (built with -tags gui)
├── gui_actions.go # UI fetch / download wiring
├── gui_browser_login.go # UI sign-in state, cancellation, and feedback
├── gui_theme.go # Dark Crunchyroll-style Fyne theme
├── gui_log.go # Download progress log in the UI
├── gui_progress.go # Download progress bar tracking
├── gui_convert.go # Convert tab, file/folder picker, and drag-and-drop
├── catalog.go # Available audio/subtitle/quality lookup per title
├── converter.go # Cancellable FFmpeg video conversion
├── flags.go # Shared CLI/GUI option defaults
├── url.go # Crunchyroll URL parsing
├── resolve.go # Episode/season GUID resolution for the requested dub
├── config.go # Saved settings in ~/.crunchyroll.config/config.json
├── cancel.go # Cancellation context for stopping a download run
├── download.go # Episode + season download orchestration, segment fetching
├── episode.go # Playback API, episode metadata, stream teardown
├── season.go # Season list + episode list from CMS API
├── mpd.go # DASH manifest parsing, video/audio representation selection
├── drm.go # Widevine PSSH extraction, license request, key decryption
├── output.go # FFmpeg mux (video + audio + subtitles → MKV)
├── token.go # OAuth token from etp_rt cookie, expiry tracking
├── browser_login.go # Managed Chromium login and cookie extraction
├── http_request.go # Pooled HTTP clients, bounded 401 retry + token refresh
├── utils.go # Language display name mapping
├── go.mod
├── build.sh # Build the CLI binary into bin/
├── build_UI.sh # Build the desktop UI binary into bin/
├── release.sh # Tag + push release helper script
├── CHANGELOG.md
└── README.md
- Go (for building from source)
- A C compiler for the desktop UI (Xcode Command Line Tools on macOS,
gcc/libglon Linux, MinGW on Windows) - FFmpeg (must be in PATH)
- A Crunchyroll account (Premium required for Premium-only content)
- Chrome, Edge, Brave, or Chromium for automatic browser sign-in (manual cookie entry remains available)
- A Widevine CDM — either a
.wvdfile, or aclient_id.bin+private_key.pempair
Download the latest binary from the releases page for your platform, or build from source:
git clone https://github.com/MantisWare/crunchyroll-downloader.git
cd crunchyroll-downloader
./build.shThe CLI binary is output to bin/crunchyroll-downloader.
./build_UI.sh
./bin/crunchyroll-downloader-guiThe desktop app has two tabs:
- Click Sign in with browser and complete the Crunchyroll login in the temporary browser window
- The app captures the session cookie automatically and removes the temporary browser profile
- Paste a Crunchyroll series or watch URL and click Lookup
- The UI reveals the audio/dub, subtitle, quality, and season options available for that title
- Series URLs show a season picker and episode checklist; episode URLs show that one episode
- Select episodes and click Download selected — a progress bar at the bottom tracks the run
- Click Stop to interrupt a download in progress; partial files are cleaned up
- Click Reset to clear the URL, episode list, and log so you can paste another link
- Open the Convert tab.
- Drop one or more video files—or a folder—onto the tab. You can also use Choose file or Choose folder.
- Select the target video and audio quality.
- Click Convert. FFmpeg creates H.264/AAC MP4 files named like
Show S01E02 Episode Title [720p].mp4. - A folder conversion writes its files into a
converted_720p/folder inside the selected folder. - Click Stop to cancel the current FFmpeg process and the remaining queue.
Supported inputs are MP4, MKV, MOV, AVI, WebM, M4V, FLV, and WMV. Folder conversion processes supported files directly inside the selected folder.
Settings are stored in ~/.crunchyroll.config/config.json (created on first launch). That file keeps your etp_rt cookie, audio/subtitle languages, video and audio quality, download folder, and the window size. The CLI also reads etp_rt from there if you omit -etp-rt.
The -s -w flags strip debug symbols for a smaller CLI binary if you build by hand:
go build -ldflags="-s -w" -o bin/crunchyroll-downloader .In the desktop UI, click Sign in with browser. For the CLI, add -browser-login:
./bin/crunchyroll-downloader -browser-loginThis can be run by itself to save the login, or together with -url/-urls to continue directly into a download. The app launches a supported Chromium-based browser with an isolated temporary profile. Enter your credentials directly on Crunchyroll; the downloader never receives your password, 2FA code, or CAPTCHA response. Once Crunchyroll issues the etp_rt session cookie, the app saves it in ~/.crunchyroll.config/config.json, closes the temporary session, and removes its profile.
Browser sign-in times out after 10 minutes and can be cancelled from the desktop UI or with Ctrl+C in the CLI.
- Go to crunchyroll.com and log in
- Open Developer Tools
- Firefox: Storage → Cookies
- Chrome: Application → Cookies
- Select the Crunchyroll domain and copy the
etp_rtcookie value
Crunchyroll uses DRM-protected content. You need a .wvd file (or client_id.bin + private_key.pem) to obtain decryption keys. If you don't have a rooted Android device, search "ready to use cdms" — there are plenty of sources.
Place your CDM files in any of these locations (checked in order):
- Current working directory (
.) assets/relative to the working directoryassets/relative to the binary location
Usage of ./crunchyroll-downloader:
-audio-lang string
Audio language (default "ja-JP")
-audio-quality string
Audio quality (default "192k")
-browser-login
Open a browser to sign in and capture the etp_rt cookie
-dub-fallback
Download the default dub when the selected audio language is unavailable
instead of skipping the episode
-etp-rt string
The "etp_rt" cookie value of your account
-season int
Season number. Not used if an episode link is entered
-subs-lang string
Subtitles language (default "en-US")
-url string
URL of the episode/season to download
-urls string
Path to a text file with one URL per line
-video-quality string
Video quality (default "1080p")
./crunchyroll-downloader \
--url https://www.crunchyroll.com/series/GJ0H7Q5ZJ/hells-paradise \
--season 1 \
--audio-lang en-US \
--etp-rt your_token_here./crunchyroll-downloader \
--url https://www.crunchyroll.com/watch/GE00198973JAJP/dawn-and-confusion \
--audio-lang ja-JP \
--subs-lang en-US \
--etp-rt your_token_here./crunchyroll-downloader \
--urls list.txt \
--audio-lang pt-BR \
--subs-lang pt-BR \
--etp-rt your_token_hereThe text file should contain one URL per line. Invalid URLs are skipped.
Audio and subtitle languages use BCP 47 locale codes. Available options depend on what Crunchyroll provides per title.
| Code | Language |
|---|---|
ja-JP |
Japanese |
en-US |
English |
en-IN |
English (India) |
es-419 |
Español (Latin America) |
es-ES |
Español (Spain) |
pt-BR |
Português (Brazil) |
pt-PT |
Português (Portugal) |
fr-FR |
Français |
de-DE |
Deutsch |
it-IT |
Italiano |
ru-RU |
Русский |
ar-SA |
العربية |
hi-IN |
हिंदी |
ko-KR |
한국어 |
zh-CN |
中文 (Mandarin) |
zh-TW |
中文 (Taiwanese) |
id-ID |
Bahasa Indonesia |
ms-MY |
Bahasa Melayu |
th-TH |
ไทย |
vi-VN |
Tiếng Việt |
tr-TR |
Türkçe |
pl-PL |
Polski |
ca-ES |
Català |
ta-IN |
தமிழ் |
te-IN |
తెలుగు |
zh-HK |
中文 (Cantonese) |
- Authenticate — optionally captures
etp_rtthrough an isolated browser login, then exchanges it for a Bearer access token (auto-refreshes on expiry) - Resolve content — fetches episode metadata from the CMS API; for season URLs, lists all episodes in the season
- Select audio dub — if the requested
-audio-langdiffers from the episode's default, looks up the correct version GUID from the available dubs and switches to it; episodes without that dub are skipped unless-dub-fallback(the GUI's "Use default if missing" checkbox) is set, in which case the default audio is downloaded and subtitles are kept - Fetch playback — calls the playback API with the resolved GUID to get the DASH manifest, subtitle URLs, and Widevine token
- Parse manifest — extracts video and audio adaptation sets from the MPD, selects representations matching the requested quality
- Obtain keys — extracts PSSH from the manifest, sends a Widevine license request, and retrieves content decryption keys
- Download segments — fetches all DASH segments in parallel (10 workers) with retry + backoff
- Decrypt — decrypts the MP4 segments using the Widevine keys
- Download subtitles — fetches the
.asssubtitle file for the requested language (if available) - Mux — runs FFmpeg to combine video + audio + subtitles into a single MKV with embedded metadata
- Cleanup — removes temporary segment and subtitle files, notifies Crunchyroll the stream has ended
- Season retry — after every episode in the season has been attempted, checks the output folder for missing or tiny files and retries those episodes (up to two extra passes)
GitHub Actions handles cross-platform builds and releases automatically.
Every push to main and every pull request builds binaries for all supported platforms:
| Platform | Architecture | Binary Name |
|---|---|---|
| Linux | amd64 | crunchyroll-downloader-linux-amd64 |
| Linux | arm64 | crunchyroll-downloader-linux-arm64 |
| macOS | amd64 | crunchyroll-downloader-darwin-amd64 |
| macOS | arm64 | crunchyroll-downloader-darwin-arm64 |
| Windows | amd64 | crunchyroll-downloader-windows-amd64.exe |
All builds use CGO_ENABLED=0 for fully static binaries with no external C dependencies.
Use the release script — it validates the version, checks for uncommitted changes, verifies a CHANGELOG entry exists, then tags and pushes:
./release.sh 1.3.0The script will:
- Validate the semver format
- Ensure your working tree is clean
- Check that the tag doesn't already exist
- Verify
CHANGELOG.mdhas a matching entry - Show a summary and ask for confirmation
- Create an annotated git tag and push it to origin
The push triggers GitHub Actions, which builds all platforms, generates a SHA-256 checksum file, and creates a GitHub Release with auto-generated release notes.
You can also tag manually if you prefer:
git tag -a v1.3.0 -m "Release v1.3.0"
git push origin v1.3.0# CLI for the current OS/arch → bin/
./build.sh
# Desktop UI for the current OS/arch → bin/
./build_UI.sh
# CLI by hand
go build -ldflags="-s -w" -o bin/crunchyroll-downloader .
# Cross-compile CLI for Linux arm64
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -ldflags="-s -w" -o bin/crunchyroll-downloader-linux-arm64 .The GUI cannot be fully statically cross-compiled (CGO_ENABLED=0) because Fyne needs the platform windowing libraries. Build it on each target OS with ./build_UI.sh.
[Add your license here]
Forked and maintained by Mantisware.
