Skip to main content

Spotify track and playlist metadata library

Project description

GitHub stars GitHub forks License Repo size Last commit Issues Top language PyPI - Version PyPI - Python Version PyPI - Downloads Python Selenium

๐Ÿš€ Syncify

Syncify is a Python library + CLI that fetches Spotify track, playlist, and liked-song metadata directly from open.spotify.com pages โ€” great for quick metadata lookups, playlist introspection, and tooling where you don't want to wire up OAuth.

Heads up: Syncify scrapes Spotify's web UI (via Selenium). Selectors can break if Spotify updates their site.

โœจ Features

  • Track metadata: title, artist, cover image URL, and track ID from a track URL
  • Playlist metadata: playlist title, cover image URL, playlist ID, and all track URLs
  • Liked Songs: scrape your full Spotify liked-songs library โ€” opens a real browser window so you can log in, then collects every track URL automatically
  • CLI-first: run syncify <url>, syncify --likes, or python -m syncify ...
  • Auto-detect URLs: mix track + playlist URLs in one command
  • No OAuth setup: does not require Spotify API keys/tokens

๐Ÿง  How It Works

  • Input: Spotify track/playlist URLs or --likes flag
  • URL detection: a lightweight regex-based detector determines whether each URL is a Track or Playlist
  • Extraction:
    • Tracks: Selenium loads the page and extracts title/artist/image from page elements
    • Playlists: Selenium loads the page in headless mode, scrolls through the virtualised track list, and collects every track link
    • Liked Songs: Selenium opens a visible browser window, navigates to the Spotify login page, and polls the DOM for track elements โ€” proceeding the instant your liked songs are rendered (no fixed waits)
  • Output:
    • Library: returns dataclasses (TrackDetails, PlaylistDetails, LikesDetails)
    • CLI: prints a readable summary plus track URLs

๐Ÿ›  Tech Stack

  • Language: Python
  • Automation/scraping: Selenium (headless Chrome for tracks/playlists, visible Chrome for liked songs)
  • Driver management: webdriver-manager (fallback if Selenium driver resolution fails)
  • HTML parsing (small helper): BeautifulSoup4
  • HTTP: requests

๐Ÿ“ฆ Installation

Prerequisites

  • Python: 3.9+ recommended (packaging allows older, but tested targets are 3.9โ€“3.12)
  • Google Chrome installed (used by Selenium)

Install from PyPI (recommended)

pip install syncify-py

Then use:

  • CLI: syncify ...
  • Python import: from syncify import ...

Install from GitHub

pip install "git+https://github.com/adelelawady/Syncify.git"

Install locally (for development)

git clone https://github.com/adelelawady/Syncify.git
cd Syncify
pip install -e ".[dev]"

Install from source tree (non-editable)

pip install .

โš™๏ธ Configuration

Syncify has no required environment variables.

Runtime requirements

  • Chrome available on PATH / installed normally
  • Chromedriver is handled automatically via Selenium's driver resolution, with a fallback to webdriver-manager.

Troubleshooting

  • If Selenium can't start Chrome:
    • Ensure Chrome is installed and up to date.
    • Try upgrading Selenium and webdriver-manager:
pip install -U selenium webdriver-manager
  • If playlist results are incomplete:

    • Spotify's UI loads tracks lazily; the scraper scrolls, but very large playlists may take longer.
  • If liked songs time out:

    • Increase --login-timeout (default is 120 seconds).
    • Make sure you complete the login โ€” including any Spotify challenge/captcha pages โ€” before the timeout expires.

๐Ÿš€ Usage

As a library

from syncify import get_track, get_playlist, get_likes

# Track
track = get_track("https://open.spotify.com/track/5nJ4Zzqc2UjwSaIcv7bGjx")
print(track.track_title, "-", track.artist_title)
print(track.track_image_url)

# Playlist
playlist = get_playlist("https://open.spotify.com/playlist/5YOevUTnavVClJ0hAslu0N")
print(playlist.title)
print("Tracks:", len(playlist.track_urls))
print(playlist.track_urls[:5])

# Liked Songs  โ€” opens a browser window for you to log in
likes = get_likes()
print(likes.total_tracks)
for url in likes.track_urls:
    print(url)

# Give yourself more time to log in
likes = get_likes(login_timeout=180)

get_likes() parameters

Parameter Type Default Description
login_timeout int 120 Seconds to wait for login + page render. Proceeds immediately once ready.
page_load_timeout int 30 Selenium page-load timeout in seconds.
scroll_pause float 2.0 Pause between scroll steps in seconds.

As a CLI

After installation, you can use either:

  • syncify ... (console script), or
  • python -m syncify ... (module execution)
# Auto-detect URL type (track or playlist)
syncify https://open.spotify.com/track/5nJ4Zzqc2UjwSaIcv7bGjx
syncify https://open.spotify.com/playlist/5YOevUTnavVClJ0hAslu0N

# Explicit type
syncify --track https://open.spotify.com/track/...
syncify --playlist https://open.spotify.com/playlist/...

# Fetch your liked songs (opens a browser window for login)
syncify --likes

# Give yourself more time to log in
syncify --likes --login-timeout 180

# Multiple URLs (mixed types supported)
syncify <url1> <url2> <url3>

CLI flags

syncify --track <URL>                          # fetch a single track
syncify --playlist <URL>                       # fetch a playlist
syncify --likes                                # fetch your liked songs
syncify --likes --login-timeout <SECONDS>      # custom login timeout (default 120)
syncify <URL> [URL ...]                        # auto-detect, multiple URLs

๐Ÿ“ก API Reference

get_track(url: str) -> TrackDetails

Fetch metadata for a Spotify track URL.

Field Type Description
spotify_url str Original Spotify URL
track_id str Spotify track ID
track_title str Song title
artist_title str Artist name
track_image_url str Cover image URL

get_playlist(url: str) -> PlaylistDetails

Fetch metadata for a Spotify playlist URL.

Field Type Description
playlist_url str Original Spotify URL
playlist_id str Spotify playlist ID
title str Playlist title
playlist_image_url str Cover image URL
track_urls list[str] All track URLs in the playlist

get_likes(login_timeout, page_load_timeout, scroll_pause) -> LikesDetails

Fetch all tracks from your Spotify Liked Songs library. Opens a visible browser window for authentication.

Field Type Description
track_urls list[str] All liked track URLs
total_tracks int Total number of liked tracks (property)
from syncify.spotify.Spotify_likes_info import LikesDetails, get_likes

# Basic usage โ€” opens browser, waits for login
details = get_likes()

# Give yourself more time to log in
details = get_likes(login_timeout=180)

print(details.total_tracks)
for url in details.track_urls:
    print(url)

Note: get_likes() opens a real (non-headless) Chrome window and navigates to the Spotify login page. It polls the DOM every second and proceeds the instant your liked songs are rendered โ€” you are never made to wait longer than necessary.

๐Ÿ“‚ Project Structure

Syncify/
โ”œโ”€ syncify/
โ”‚  โ”œโ”€ __init__.py              # Public API exports
โ”‚  โ”œโ”€ __main__.py              # CLI: `python -m syncify` / `syncify`
โ”‚  โ””โ”€ spotify/
โ”‚     โ”œโ”€ Spotify_track_info.py
โ”‚     โ”œโ”€ Spotify_playlist_info.py
โ”‚     โ”œโ”€ Spotify_likes_info.py     # โ† Liked Songs scraper
โ”‚     โ”œโ”€ utils.py
โ”‚     โ””โ”€ __init__.py
โ”œโ”€ main.py                     # Convenience script wrapper
โ”œโ”€ pyproject.toml              # Modern packaging + dependencies
โ”œโ”€ setup.py                    # Legacy packaging (mirrors pyproject)
โ”œโ”€ requirements.txt            # Dev-friendly requirements list
โ””โ”€ README.md

๐Ÿงช Development

git clone https://github.com/adelelawady/Syncify.git
cd Syncify
python -m venv .venv

# Windows PowerShell
.venv\Scripts\Activate.ps1

pip install -e ".[dev]"

# Run the CLI against a URL
python -m syncify https://open.spotify.com/track/<id>

# Fetch liked songs
python -m syncify --likes --login-timeout 180

Suggested checks:

python -c "from syncify import get_track; print(get_track('https://open.spotify.com/track/<id>').track_title)"
python -c "from syncify import get_likes; d = get_likes(); print(d.total_tracks)"

๐Ÿค Contributing

Contributions are welcome!

  • Bugs/requests: open an issue with a minimal repro (URL + expected vs actual output)
  • PRs:
    • Keep changes focused and include a clear description
    • Prefer small, well-scoped improvements to selectors and parsing logic
    • Avoid committing local artifacts (.venv/, build/, syncify.egg-info/)

If you're adding new scraping logic, please include:

  • A sample Spotify URL (track/playlist) that the change targets
  • A note about which DOM selectors were relied on and why

๐Ÿ“œ License

MIT (as declared in package metadata).

Tip: consider adding a top-level LICENSE file so GitHub can display the license automatically.

โญ Support

If you find Syncify useful, please star the repo โ€” it helps others discover the project and motivates continued maintenance.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

syncify_py-2.2.0.tar.gz (19.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

syncify_py-2.2.0-py3-none-any.whl (18.6 kB view details)

Uploaded Python 3

File details

Details for the file syncify_py-2.2.0.tar.gz.

File metadata

  • Download URL: syncify_py-2.2.0.tar.gz
  • Upload date:
  • Size: 19.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.0

File hashes

Hashes for syncify_py-2.2.0.tar.gz
Algorithm Hash digest
SHA256 f74a35db452497b8a0b7ef8b5dae527c0aef0bd394899f7f5cdaae6972501109
MD5 d015d5175e76d0caa6126117d4bb76d6
BLAKE2b-256 331f42552aaef3822f2520a38e6efb62e4b804719437cb6123b7e293be558b4d

See more details on using hashes here.

File details

Details for the file syncify_py-2.2.0-py3-none-any.whl.

File metadata

  • Download URL: syncify_py-2.2.0-py3-none-any.whl
  • Upload date:
  • Size: 18.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.0

File hashes

Hashes for syncify_py-2.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 33a7bc18bf294e8835813a955e0a336506699d1f0d974d0b827dbc4468e8c96a
MD5 ea6875c86b7f958d44157be5195f818c
BLAKE2b-256 5ab0b999c233783e32f6023374a0a37b18fe51ca53dcd3e74a4aa185ee3800d8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page