Zvuk Grabber ๐ต
Zvuk (ะะฒัะบ) grabber written in Go.
This tool allows you to download artists, albums, tracks, and playlists from Zvuk.
Quick Start ๐
-
Download the Latest Release:
Grab the pre-built binary for your OS from the Releases page.
-
Extract the Archive:
Just extract the archive! It already has everything you need inside.
-
Set Up Authentication Token:
Option 1: Automatic Browser Login (Recommended)
Run the interactive login command:
zvuk-grabber auth login
This will:
- Open a browser window
- Let you log in manually (phone number + SMS code)
- Automatically extract and save your auth token
- Update your
.zvuk-grabber.yaml configuration
Option 2: Manual Token Extraction
Open the .zvuk-grabber.yaml file and set your auth_token.
You can obtain it by logging into Zvuk's API and locating the token in the JSON response using the JSON path $.result.profile.token.
-
Run the Tool:
-
Enjoy Your Music! ๐ถ
Start downloading your favorite tracks, albums, and playlists.
Installation ๐ ๏ธ
Download Pre-built Binaries
Pre-built binaries for macOS, Windows, and Linux (for both arm64 and amd64 architectures) are available on the Releases page.
-
Download the Correct Binary:
Go to the Releases page and download the appropriate binary for your operating system and architecture.
Replace 1.0.0 in the filenames below with the latest version number:
- macOS:
zvuk-grabber_1.0.0_darwin_amd64.tar.gz for Intel-based Macs (amd64).
zvuk-grabber_1.0.0_darwin_arm64.tar.gz for Apple Silicon Macs (arm64).
- Windows:
zvuk-grabber_1.0.0_windows_amd64.zip for 64-bit Windows (amd64).
zvuk-grabber_1.0.0_windows_arm64.zip for ARM-based Windows (arm64).
- Linux:
zvuk-grabber_1.0.0_linux_amd64.tar.gz for 64-bit Linux (amd64).
zvuk-grabber_1.0.0_linux_arm64.tar.gz for ARM-based Linux (arm64).
-
Extract the Bundle:
Each bundle contains the following files:
zvuk-grabber (or zvuk-grabber.exe for Windows): The main executable.
.zvuk-grabber.yaml: The configuration file.
LICENSE: The license file.
README.md: The documentation.
Extract the bundle to your desired location:
tar -xvzf zvuk-grabber_1.0.0_darwin_amd64.tar.gz # For macOS/Linux
unzip zvuk-grabber_1.0.0_windows_amd64.zip # For Windows
-
Set Up Authentication Token:
Automatic (Recommended):
zvuk-grabber auth login
Manual: Open the .zvuk-grabber.yaml file and set your authentication token in the auth_token field.
You can obtain the token by logging into Zvuk's API and locating the token using the JSON path $.result.profile.token.
-
Run the Binary:
-
Linux/macOS:
Make the binary executable and run it:
chmod +x zvuk-grabber # Make the file executable
./zvuk-grabber # Run the tool
-
Windows:
Simply run the executable:
zvuk-grabber
Building from Source (Optional) ๐ ๏ธ
If you want to modify the code or build the binary yourself, you'll need the following prerequisites:
-
Install Go:
Download and install Go from the official website.
-
Install Task:
Task is a task runner/build tool that simplifies the build process.
Install it by following the instructions on their official website.
-
Clone the Repository:
Clone the repository to your local machine:
git clone https://github.com/oshokin/zvuk-grabber.git
cd zvuk-grabber
-
Build the Binary:
Use Task to build the binary:
task build
The compiled binary will be stored in the bin/ directory.
Authentication ๐
Browser-Based Login (The Easy Way)
I've wanted to automate the authentication cookie extraction for ages! But as we all know, UI/UX automation is usually painful because we approach the website like a black box and poke it with a stick hoping to discover the right behavior and side effects. Like a blind chicken in the dark, basically.
But IT WORKS! Well... mostly.
The Good News
Run this command and watch the magic happen:
zvuk-grabber auth login
This will:
- Open a browser window (Chrome/Chromium) with stealth mode enabled
- Navigate to the Zvuk homepage (to establish proper origin for OAuth)
- Wait for you to manually log in (phone number + SMS code)
- Simulate human behavior while waiting (mouse movements, scrolling, random delays)
- Detect when login completes and OAuth flow finishes
- Extract the
auth cookie from your browser
- Save it to
.zvuk-grabber.yaml
- Close the browser and celebrate
Anti-Bot Detection Stack
The tool employs multiple techniques to evade bot detection:
-
Stealth Mode (go-rod/stealth)
- Hides
navigator.webdriver flag
- Patches browser automation signatures
- Spoofs plugin lists and permissions
- Makes CDP (Chrome DevTools Protocol) invisible
-
Human Behavior Simulation
- Random mouse movements across the page
- Occasional scrolling (up/down)
- Variable timing between actions (500ms-2s)
- Random pauses to mimic reading/thinking
- Randomized interaction patterns
-
Fresh Browser Profile
- Each login uses a temporary incognito profile
- No persistent cookies or history between sessions
- Clean slate helps avoid detection patterns
-
Smart OAuth Flow
- Starts on
zvuk.com domain (not login page directly)
- Avoids CORS errors during OAuth callback
- Bypasses broken automatic redirects manually
- Detects auth cookie directly without rate-limited API calls
The Bad News (Windows Edition)
On Windows 10 with ESET Security, you might get a fun notification that our code is infected with some virus. It's not. Both this project and go-rod have source code available - feel free to audit it yourself.
TL;DR: It's a false positive. Ignore the warning or whitelist the application.
Troubleshooting Login Issues
If the login process gets stuck or fails:
-
Enable debug logging in .zvuk-grabber.yaml:
log_level: debug
-
Run the command again:
zvuk-grabber auth login
-
Create an issue with the debug output
And if the moon phase is in the right wavelength of light and Mercury's retrograde isn't too retrograde, I might just take a look at what's going on in your code.
Known Issues
- CORS/API Issues: Zvuk's OAuth callback sometimes fails with CORS errors. The tool now automatically bypasses this by manually redirecting to the main page.
- Rate Limiting: If you try too many times, Zvuk might rate-limit you. The tool now minimizes API calls during login to avoid this.
- Browser Compatibility: Works best with Chrome/Chromium. Firefox might work but is untested.
- Cleanup Warnings: You might see warnings about temp directory cleanup on Windows. This is normal and non-critical - Chrome takes time to release file locks.
If the browser automation fails or you prefer doing things manually:
-
Log in to Zvuk in your browser
-
Navigate to https://zvuk.com/api/v2/tiny/profile
-
Find the token in the JSON response at $.result.profile.token
-
Copy it to .zvuk-grabber.yaml:
auth_token: "your_token_here"
Usage ๐ง
Downloading Content
-
Download Albums:
To download one or more albums, provide the album URLs as arguments:
zvuk-grabber https://zvuk.com/release/36599795 https://zvuk.com/release/37212880
-
Download Tracks:
To download individual tracks, provide the track URLs.
The tracks will be organized as if they were part of an album, with a folder and cover art:
zvuk-grabber https://zvuk.com/track/67856297 https://zvuk.com/track/51397074 https://zvuk.com/track/63391919 https://zvuk.com/track/106773860 https://zvuk.com/track/114947212
-
Download Playlists:
To download a playlist, provide the playlist URL:
zvuk-grabber https://zvuk.com/playlist/9037842
-
Download Artists:
To download an artist's entire discography, provide the artist URL:
zvuk-grabber https://zvuk.com/artist/3196437
-
Using Text Files:
You can also provide text files containing URLs (one per line):
zvuk-grabber 1.txt 2.txt
Command-Line Flags
You can override configuration settings using command-line flags:
zvuk-grabber [flags] {urls}
Available flags:
-c, --config <path> - Path to configuration file (default: .zvuk-grabber.yaml)
-f, --format <1-3> - Audio format:
1 = MP3, 128 Kbps
2 = MP3, 320 Kbps
3 = FLAC, 16-bit/44.1kHz
-o, --output <path> - Output directory for downloads
-l, --lyrics - Download lyrics if available
-s, --speed-limit <speed> - Download speed limit (e.g., 500KB, 1MB, 1.5MB)
Examples:
# Download album in FLAC format
zvuk-grabber -f 3 https://zvuk.com/release/3393328
# Download with custom output directory and lyrics
zvuk-grabber -o "/Music/Zvuk" -l https://zvuk.com/release/5895112
# Download with speed limit
zvuk-grabber -s 1MB https://zvuk.com/release/8045705
# Combine multiple flags
zvuk-grabber -f 3 -o "/Music" -l -s 2MB https://zvuk.com/release/38858441
Available Commands
zvuk-grabber {urls} - Download content from URLs
zvuk-grabber auth login - Interactive browser-based authentication
zvuk-grabber version - Show version information
zvuk-grabber help - Show help information
Configuration โ๏ธ
The default configuration is already set in the .zvuk-grabber.yaml file.
You only need to modify it if you want to customize the behavior.
Key options include:
Authentication
-
auth_token: Your Zvuk API authentication token.
Easiest way: Run zvuk-grabber auth login to automatically extract it.
Manual way: Log in to Zvuk's API and locate the token using the JSON path $.result.profile.token.
Example:
auth_token: "a3f8e7b2c5d946f1a0b9e8d7c6f5e4a2"
download_format: Preferred audio format for downloaded files.
Available options:
-
1 = MP3, 128 Kbps (standard quality)
-
2 = MP3, 320 Kbps (high quality)
-
3 = FLAC, 16/24-bit (lossless quality)
Example:
download_format: 3
Output Settings
-
output_path: Directory where downloaded files will be saved.
You can specify either a relative path (e.g., "zvuk downloads") or an absolute path (e.g., "C:/Music").
Example:
output_path: "zvuk downloads"
-
create_folder_for_singles: Whether to create a separate folder for single tracks (tracks not part of an album).
If set to false, single tracks will be saved directly in the output directory.
Example:
create_folder_for_singles: false
-
max_folder_name_length: Maximum length for folder names created by the application.
This ensures folder names remain readable and compatible across different operating systems.
Set to 0 to avoid cutting folder names.
Example:
max_folder_name_length: 100
File Naming Templates
-
track_filename_template: Track file naming format.
Available placeholders:
-
{{.albumArtist}}: Primary artist(s) of the album.
-
{{.albumID}}: Unique identifier for the album.
-
{{.albumTitle}}: Title of the album.
-
{{.albumTrackCount}}: Total number of tracks in the album.
-
{{.collectionTitle}}: Title of the album.
-
{{.recordLabel}}: Name of the record label.
-
{{.releaseDate}}: Full release date of the album (YYYY-MM-DD format).
-
{{.releaseYear}}: Year the album was released.
-
{{.trackArtist}}: Artist(s) of the track.
-
{{.trackCount}}: Total number of tracks in the album.
-
{{.trackGenre}}: Genre(s) of the track.
-
{{.trackID}}: Unique identifier for the track.
-
{{.trackNumber}}: Track number within the album (without leading zeros).
-
{{.trackNumberPad}}: Track number with two-digit padding (e.g., 01, 02).
-
{{.trackTitle}}: Track title.
-
{{.type}}: "album" (used to differentiate album tracks).
Example:
track_filename_template: "{{.trackNumberPad}} - {{.trackTitle}}"
-
album_folder_template: Album folder naming format.
Available placeholders:
-
{{.albumArtist}}: Primary artist(s) of the album.
-
{{.albumID}}: Unique identifier for the album.
-
{{.albumTitle}}: Title of the album.
-
{{.albumTrackCount}}: Total number of tracks in the album.
-
{{.releaseDate}}: Full release date of the album (YYYY-MM-DD format).
-
{{.releaseYear}}: Year the album was released.
-
{{.type}}: "album" (used to differentiate albums from playlists).
Folder Structure Tip: Use / or \ in your template to create nested subfolders.
Both separators work universally across operating systems - we'll automatically convert them to your system's native format.
Examples:
# Unix-style path (recommended)
album_folder_template: "Artists/{{.albumArtist}}/{{.releaseYear}} - {{.albumTitle}}"
# Windows-style path (escaped backslash)
album_folder_template: "Music\\{{.albumArtist}}\\{{.releaseYear}} - {{.albumTitle}}"
# Flat structure alternative
album_folder_template: "{{.releaseYear}} - {{.albumArtist}} - {{.albumTitle}}"
-
playlist_filename_template: Playlist file naming format.
Available placeholders:
-
{{.albumArtist}}: Primary artist(s) of the album containing the track.
-
{{.albumID}}: Unique identifier for the album containing the track.
-
{{.albumTitle}}: Title of the album containing the track.
-
{{.albumTrackCount}}: Total number of tracks in the album.
-
{{.collectionTitle}}: Title of the playlist.
-
{{.playlistID}}: Unique identifier for the playlist.
-
{{.playlistTitle}}: Title of the playlist.
-
{{.playlistTrackCount}}: Total number of tracks in the playlist.
-
{{.recordLabel}}: Name of the record label.
-
{{.releaseDate}}: Full release date of the album containing the track (YYYY-MM-DD format).
-
{{.releaseYear}}: Year the album containing the track was released.
-
{{.trackArtist}}: Artist(s) of the track.
-
{{.trackCount}}: Total number of tracks in the playlist.
-
{{.trackGenre}}: Genre(s) of the track.
-
{{.trackID}}: Unique identifier for the track.
-
{{.trackNumber}}: Track number within the playlist (without leading zeros).
-
{{.trackNumberPad}}: Track number with two-digit padding (e.g., 01, 02).
-
{{.trackTitle}}: Track title.
-
{{.type}}: "playlist" (used to differentiate playlists from albums).
Example:
playlist_filename_template: "{{.trackNumberPad}} - {{.trackArtist}} - {{.trackTitle}}"
Download Behavior
-
download_lyrics: Whether to download lyrics for tracks (if available).
Example:
download_lyrics: true
-
replace_tracks: Whether to overwrite existing track files.
Example:
replace_tracks: false
-
replace_covers: Whether to overwrite existing cover art files.
Example:
replace_covers: false
-
replace_lyrics: Whether to overwrite existing lyric files.
Example:
replace_lyrics: false
-
download_speed_limit: Limit download speed (e.g., "1MB" for 1 MB/s).
Set to empty or 0 for unlimited speed.
Example:
download_speed_limit: ""
Retry and Pause Settings
-
retry_attempts_count: Number of retry attempts before giving up on a failed download.
Example:
retry_attempts_count: 5
-
max_download_pause: Maximum pause duration between track downloads (to mimic human behavior).
This value is in Go duration format (e.g., "2s" for 2 seconds).
Example:
max_download_pause: "2s"
-
min_retry_pause: Minimum pause duration before retrying a failed download attempt.
Helps avoid hitting API rate limits or temporary failures.
Example:
min_retry_pause: "3s"
-
max_retry_pause: Maximum pause duration before retrying a failed download attempt.
Randomized between min_retry_pause and max_retry_pause for better resilience.
Example:
max_retry_pause: "7s"
Logging
-
log_level: Logging level for the application.
Available options: debug, info, warn, error, fatal.
Default: info.
Example:
log_level: "debug"
Troubleshooting ๐
Having trouble? Follow these steps:
-
Enable Debug Logging:
Set the log_level to debug in the .zvuk-grabber.yaml file:
log_level: "debug"
Attach the logs when reporting issues.
-
Check Your Token:
Ensure your auth_token is valid and properly set in the .zvuk-grabber.yaml file.
If it's not working, run zvuk-grabber auth login to get a fresh token.
-
Check Your Internet Connection:
A stable connection is essential. If downloads are failing, wait a moment and try again.
-
Check Zvuk's API Status:
If Zvuk's API is down, check their website or API status page for updates.
Support the Project ๐
If you find Zvuk Grabber useful and want to support its development, here's how you can help:
- Create a PR:
If you're a developer, create a Pull Request with improvements or bug fixes.
Contributions are always welcome!
Bug Fixes and Updates ๐ ๏ธ
I add new features and fix bugs when the stars align, the moon's in the right phase, and my cat's purring just right.
If you're waiting for a fix, feel free to open an issue or create a PR.
Disclaimer โ ๏ธ
-
Use Zvuk Grabber responsibly and in compliance with the laws of your country.
-
Zvukโs brand and name are trademarks of their respective owners.
-
Zvuk Grabber is not affiliated, sponsored, or endorsed by Zvuk.