# How to Download and Save Album Covers Alongside Music Files in Spotify-Saver

> Learn how Spotify-Saver downloads and saves album covers with your music. Extract high-res artwork URLs and embed them or save separate JPG files alongside tracks.

- Repository: [Gabriel Baute/spotify-saver](https://github.com/gabrielbaute/spotify-saver)
- Tags: how-to-guide
- Published: 2026-03-02

---

**Spotify-Saver downloads album covers by extracting high-resolution artwork URLs from Spotify metadata and processing them through the `ImageDownloader` service, either embedding the image bytes directly into audio file metadata or saving separate `cover.jpg` files alongside track collections.**

When using the open-source **Spotify-Saver** tool to build your local music library, proper album artwork handling ensures your collection displays correctly across media players. This article examines how the `gabrielbaute/spotify-saver` repository implements cover art retrieval and storage, detailing the two distinct workflows for handling album covers alongside downloaded audio files.

## How Album Cover Downloading Works

The application retrieves cover art through a coordinated pipeline involving Spotify's API, a dedicated image download service, and metadata embedding utilities. Two primary flows handle artwork depending on whether you download individual tracks or complete collections.

### Extracting Cover Art URLs from Spotify Metadata

The process begins in [`spotifysaver/services/spotify_api.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/spotifysaver/services/spotify_api.py), where the `SpotifyAPI` class constructs data models containing high-resolution cover art URLs. When processing tracks, albums, or playlists, the code extracts the first (highest resolution) image from Spotify's metadata response:

```python

# spotifysaver/services/spotify_api.py

cover_url = raw_data["images"][0]["url"] if raw_data["images"] else None

```

This `cover_url` field populates the `Track`, `Album`, and `Playlist` model classes defined in `spotifysaver/models/`, making the artwork address available throughout the download pipeline.

### The ImageDownloader Service

All HTTP image fetching logic resides in [`spotifysaver/downloader/image_downloader.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/spotifysaver/downloader/image_downloader.py). This thin wrapper around the `requests` library provides two key methods:

- **`download_image(url, output_path)`**: Writes image bytes directly to disk (lines 15-38)
- **`get_image_from_url(url)`**: Returns raw bytes for in-memory processing (lines 45-61)

The implementation handles directory creation and timeout configuration:

```python

# spotifysaver/downloader/image_downloader.py

response = requests.get(url, timeout=Config.DOWNLOAD_TIMEOUT)
output_path.parent.mkdir(parents=True, exist_ok=True)
output_path.write_bytes(response.content)          # saved to disk

# or return response.content for in-memory use

```

### Embedding Covers into Audio Files

For single track downloads, Spotify-Saver embeds artwork directly into the audio file's metadata tags. In [`spotifysaver/downloader/youtube_downloader.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/spotifysaver/downloader/youtube_downloader.py), the `YouTubeDownloader._download_cover()` method (lines 197-208) retrieves image bytes via `ImageDownloader.get_image_from_url()`, then passes them to `MusicFileMetadata`:

```python

# youtube_downloader.py

cover_data = self._download_cover(track)          # bytes or None

metadata = MusicFileMetadata(file_path=output_path,
                               track=track,
                               cover_data=cover_data)
metadata.add_metadata()                           # embeds image

```

The `MusicFileMetadata` class in [`spotifysaver/metadata/music_file_metadata.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/spotifysaver/metadata/music_file_metadata.py) handles writing these bytes into ID3 tags (for MP3) or MP4 metadata (for M4A), ensuring the cover displays in any standard media player.

### Saving Separate Cover Image Files

When downloading complete albums or playlists, the application saves a standalone `cover.jpg` file alongside the audio tracks. The `YouTubeDownloader._save_cover_album()` method (lines 267-282) orchestrates this process:

```python

# youtube_downloader.py

def _save_cover_album(self, url: str, output_path: Path):
    image = self.image_downloader.download_image(url, output_path)
    if image:
        self.logger.info(f"Cover saved in: {output_path}")

```

CLI commands in [`spotifysaver/cli/commands/download/album.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/spotifysaver/cli/commands/download/album.py) (lines 145-148) and [`playlist.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/playlist.py) (lines 113-116) invoke this helper, passing `output_dir / "cover.jpg"` as the target path. This creates a folder structure like:

```

Music/
  Artist/
    Album (2023)/
      01 - Artist - Track.m4a          # audio file with embedded art

      cover.jpg                        # separate image for album view

```

## Code Implementation Examples

### Downloading a Single Track with Embedded Cover Art

When downloading individual tracks, the cover art is automatically embedded into the audio file metadata:

```python
from spotifysaver.downloader.youtube_downloader import YouTubeDownloader
from spotifysaver.models.track import Track
from spotifysaver.enums.audio_formats_enum import AudioFormat
from spotifysaver.enums.bitrates_enum import Bitrate
from pathlib import Path

# Track instance populated by SpotifyAPI

track = Track(...)

yt = YouTubeDownloader(base_dir=Path("Music"))
audio_path, updated_track = yt.download_track(
    track,
    output_format=AudioFormat.M4A,
    bitrate=Bitrate.B256,
    download_lyrics=True,
)

print(f"Saved audio: {audio_path}")          # contains embedded cover art

```

**Key call chain:** `YouTubeDownloader.download_track()` → `_download_cover()` → `ImageDownloader.get_image_from_url()` → `MusicFileMetadata.add_metadata()`.

### Downloading an Album with Separate Cover File

For complete collections, use the `cover=True` parameter to save artwork as a separate file:

```python
from spotifysaver.downloader.youtube_downloader import YouTubeDownloader
from spotifysaver.models.album import Album
from pathlib import Path

album = Album(...)                     # populated by SpotifyAPI

yt = YouTubeDownloader(base_dir=Path("Music"))
yt.download_album(album, cover=True)   # triggers _save_cover_album

```

**Key call chain:** `YouTubeDownloader.download_album()` → `_save_cover_album()` → `ImageDownloader.download_image()`.

### CLI Usage for Cover Art Preservation

Command-line users can trigger cover saving using the `--cover` flag:

```bash

# Album download with cover.jpg saved alongside tracks

spotifysaver download album "My Favorite Album" --cover

# Playlist download with cover art preservation

spotifysaver download playlist "Chill Vibes" --cover

```

These commands execute the same underlying methods as the Python API, ensuring consistent artwork handling across interfaces.

## Key Components and File Locations

- **[`spotifysaver/downloader/image_downloader.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/spotifysaver/downloader/image_downloader.py)**: Core image fetching service with `download_image()` and `get_image_from_url()` methods
- **[`spotifysaver/downloader/youtube_downloader.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/spotifysaver/downloader/youtube_downloader.py)**: Orchestrates audio downloads and cover handling via `_download_cover()` and `_save_cover_album()`
- **[`spotifysaver/services/spotify_api.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/spotifysaver/services/spotify_api.py)**: Retrieves Spotify metadata including `cover_url` fields
- **[`spotifysaver/metadata/music_file_metadata.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/spotifysaver/metadata/music_file_metadata.py)**: Embeds cover bytes into audio file tags
- **[`spotifysaver/cli/commands/download/album.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/spotifysaver/cli/commands/download/album.py)** and **[`playlist.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/playlist.py)**: CLI entry points that invoke cover saving for collections

## Summary

- **Spotify-Saver extracts high-resolution cover URLs** from Spotify's metadata API during the initial track/album lookup phase.
- **Two distinct workflows handle artwork**: embedding bytes directly into audio file metadata for single tracks, or saving separate `cover.jpg` files for album/playlist downloads.
- **The `ImageDownloader` service** in [`image_downloader.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/image_downloader.py) handles all HTTP image retrieval, supporting both disk writes and in-memory byte returns.
- **`YouTubeDownloader`** coordinates the process, calling `_download_cover()` for embedding and `_save_cover_album()` for standalone files.
- **CLI commands** support the `--cover` flag to trigger standalone cover saving for complete collections.

## Frequently Asked Questions

### Does Spotify-Saver always download album covers automatically?

Individual track downloads automatically embed cover art into the audio file metadata, but saving separate `cover.jpg` files requires explicitly setting `cover=True` when downloading albums or playlists via the API, or using the `--cover` flag in CLI commands.

### What image format does Spotify-Saver use for saved covers?

When saving standalone album artwork via `ImageDownloader.download_image()`, the application preserves the original format provided by Spotify's CDN (typically JPEG) and writes it directly to disk as `cover.jpg` without transcoding.

### Can I disable cover art embedding to save bandwidth?

The current implementation in [`youtube_downloader.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/youtube_downloader.py) always attempts to download cover art for single tracks via `_download_cover()`, but you can skip standalone cover file generation for albums by omitting the `cover=True` parameter or `--cover` flag.

### Where is the cover art stored when downloading playlists?

According to the source code in [`spotifysaver/cli/commands/download/playlist.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/spotifysaver/cli/commands/download/playlist.py) (lines 113-116), playlist covers are saved as `cover.jpg` in the root playlist directory, using the same `YouTubeDownloader._save_cover_album()` method employed for album downloads.