Skip to content

TasmeTime/spotify-ad-skipper

Repository files navigation

🎵 Spotify Ad Skipper

Silently skip Spotify ads on Windows — automatically, or with a single hotkey.

Python Windows License PRs Welcome

Tired of Spotify ads interrupting your flow?
This lightweight Windows utility runs in the background, intelligently detects when an advertisement is playing, and restarts Spotify to skip it — all without stealing focus or interrupting your workflow.

✨ Features⚡ Quick Start🔧 How It Works📖 Usage🏗️ Architecture🤝 Contributing


🎬 Demo

Demo

Watch the Spotify Ad Skipper in action — automatically detecting and skipping an ad.


✨ Features

Feature Description
🎯 Automatic Ad Detection Monitors Spotify's window title — when an ad plays, the title loses the "Song — Artist" dash pattern. The utility detects this and triggers a restart. The title "Spotify Free" is never treated as an ad (it also appears when music is paused).
⌨️ Global Hotkey (Ctrl+Shift+R) Manually restart Spotify at any time with a system-wide hotkey — works even when the terminal is minimised.
🪟 Minimal & Focus-Friendly Spotify is relaunched minimised to the taskbar — no window stealing your focus, no disruption to your workflow.
🔊 Auto-Resume Playback After restarting, the utility sends a virtual media Play/Pause key press so your music resumes automatically.
🛡️ Administrator Auto-Elevation Automatically requests UAC elevation if needed (required for process termination when Spotify runs as admin).
🧩 Modular & Extensible Clean separation of concerns: process management, window detection, hotkey listening, and media key simulation are all independent modules.
📝 Verbose Logging Run with --verbose to see detailed logs of every detection, restart, and media key event.

⚡ Quick Start

Prerequisites

  • Windows 10 or 11 (uses Win32 API — not cross-platform)
  • Python 3.10+ (Download)
  • Spotify (free or premium tier — ad detection works on both)

Installation

# 1. Clone the repository
git clone https://github.com/Tasmetime/spotify_ad_skipper.git
cd spotify_ad_skipper

# 2. Install dependencies
pip install -r requirements.txt

# 3. Run it!
python main.py

Note: The first time you run it, Windows may show a UAC prompt asking for administrator privileges. This is required to terminate Spotify's process reliably. Click "Yes" to proceed.

Using start.bat

For convenience, double-click start.bat — it launches the utility with verbose logging enabled and pauses on error so you can see what went wrong.


📖 Usage

Command-Line Options

python main.py                          # Run with default settings (hotkey + auto ad skip)
python main.py --no-auto-skip           # Disable automatic ad skipping (manual hotkey only)
python main.py --verbose                # Enable detailed debug logging
python main.py --help                   # Show full help text

While Running

Action Result
Press Ctrl+Shift+R Immediately restarts Spotify (if running)
Press Ctrl+C in the terminal Gracefully shuts down the utility
Let it run in the background Ads are detected and skipped automatically every ~2 seconds

Example Output

14:32:01 [INFO] spotify_restarter: ==================================================
14:32:01 [INFO] spotify_restarter: Spotify Restarter — running in background.
14:32:01 [INFO] spotify_restarter: Press Ctrl+Shift+R to restart Spotify.
14:32:01 [INFO] spotify_restarter: Press Ctrl+C in the terminal to exit.
14:32:01 [INFO] spotify_restarter: ==================================================
14:32:05 [INFO] spotify_restarter.ad_detector: Ad detected! Window title: 'spotifyad123'
14:32:05 [INFO] spotify_restarter.orchestrator: Spotify Restarter — starting cycle.
14:32:06 [INFO] spotify_restarter.launcher: Launched Spotify from: C:\Users\...\Spotify.exe
14:32:08 [INFO] spotify_restarter.media_keys: Sent media Play/Pause via keybd_event (VK 0xB3).

🔧 How It Works

Ad Detection Logic

The core insight is how Spotify's window title changes during different states:

Normal song:      "Bohemian Rhapsody — Queen"     ✅ Contains a dash (—)
Paused / Free:    "Spotify Free"                   ✅ Never an ad (exception)
Advertisement:    "spotifyad123"                   ❌ No dash at all

The AdDetector uses these rules, evaluated in order:

  1. Spotify Free Exception — If the title is exactly "Spotify Free", it is never considered an ad, regardless of any other condition. This title appears both when the free tier is active and when music is paused, so treating it as an ad would cause false-positive restarts.
  2. Dash Check — If the window title does not contain a -, the content is classified as an ad.

Important: The detector locates Spotify windows by process ID (not by title), so it can always find the window regardless of whether the title is a song name or an ad placeholder.

The Restart Cycle

When an ad is detected (or the hotkey is pressed), the SpotifyRestarter orchestrates:

1.  CLOSE   → Send WM_CLOSE to Spotify windows
2.  DISMISS → Send Enter key to dismiss any "Are you sure?" dialog
3.  WAIT    → Poll until Spotify process exits
4.  FORCE   → If still running, escalate to terminate/kill
5.  LAUNCH  → Start Spotify minimised (no focus steal)
6.  MINIMISE→ Safety net: minimise any windows that opened normally
7.  PLAY    → Send virtual media Play/Pause key (VK_MEDIA_PLAY_PAUSE)

Administrator Privileges

Some Spotify installations run with elevated privileges, meaning a non-admin Python process cannot terminate them. The utility automatically detects this and relaunches itself via UAC using ShellExecuteW with the runas verb.


🏗️ Architecture

The project is organised into a clean, modular package:

spotify_ad_skipper/
├── main.py                              # CLI entry point & argument parsing
├── pyproject.toml                       # Project metadata & dependencies
├── requirements.txt                     # Pinned dependencies
├── start.bat                            # Convenience launcher (double-click)
├── .gitignore
│
└── spotify_restarter/                   # Core Python package
    ├── __init__.py                      # Public API exports
    ├── config.py                        # Config dataclass (paths, timeouts, thresholds)
    ├── process_manager.py               # Process discovery & termination via psutil
    ├── window_manager.py                # Win32 window enumeration & interaction
    ├── launcher.py                      # Spotify executable discovery & launch
    ├── media_keys.py                    # Virtual media key simulation (keybd_event)
    ├── ad_detector.py                   # Window title analysis & ad detection
    ├── hotkey.py                        # Global hotkey registration (Win32)
    ├── orchestrator.py                  # Full restart cycle orchestration
    └── utils.py                         # Admin check, UAC escalation, dependency guard

Module Responsibilities

Module Responsibility
config.py Central Config dataclass — all tunable parameters in one place.
process_manager.py Wraps psutil to find, inspect, and terminate Spotify processes with a polite → force escalation strategy.
window_manager.py Uses EnumWindows / GetWindowText / GetWindowThreadProcessId to enumerate top-level windows and interact with them (close, minimise, send keys).
launcher.py Searches known install paths for Spotify.exe, falls back to shell resolution, and launches with SW_SHOWMINNOACTIVE to avoid focus steal.
media_keys.py Sends VK_MEDIA_PLAY_PAUSE (0xB3) via keybd_event — the most reliable method for triggering Spotify playback.
ad_detector.py Implements the dash-check and exact-match heuristics on window titles. Runs in a daemon thread, polling every 2 seconds.
hotkey.py Registers Ctrl+Shift+R as a global hotkey via RegisterHotKey. Creates a hidden Win32 window to receive messages, then runs the message pump.
orchestrator.py SpotifyRestarter class that ties everything together — close → launch → play.
utils.py is_admin(), relaunch_as_admin() (UAC via ShellExecuteW), and check_dependencies().

⚙️ Configuration

All tunable parameters live in the Config dataclass:

Parameter Default Description
spotify_process_names ("Spotify.exe", "Spotify") Process names used by psutil to identify Spotify.
spotify_window_titles ("Spotify", "Spotify Premium", "Spotify Free") Window title substrings for matching Spotify windows.
close_attempts 3 How many times to try closing Spotify before force-killing.
close_delay 1.5 Seconds to wait after sending a close signal before checking again.
launch_timeout 15.0 Max seconds to wait for Spotify to appear after launching.
launch_check_interval 0.5 Poll interval when waiting for Spotify to start.
ad_polling_interval 2.0 Seconds between ad-detection checks.
ad_skip_enabled True Whether to automatically skip ads when detected.
launch_minimized True Launch Spotify minimised to avoid focus steal.
media_key_delay 2.0 Seconds to wait after launch before sending the play command.
spotify_known_paths (see config) Common Spotify install paths checked in order.

🧪 Dependencies

Core

Package Version Purpose
psutil ≥ 6.0.0 Cross-platform process discovery and termination.
pywin32 ≥ 310 Windows API bindings — win32gui, win32api, win32con, etc.

Optional (for experimental scripts)

Package Purpose
pycaw Audio control (experimental scripts)
keyboard System-wide media key events
pyautogui GUI automation

🤝 Contributing

Contributions are welcome! Here's how you can help:

  1. 🐛 Report Bugs — Open an issue with reproduction steps.
  2. 💡 Suggest Features — Open an issue with the enhancement tag.
  3. 🔀 Submit PRs — Fork the repo, create a feature branch, and open a pull request.

Development Setup

git clone https://github.com/Tasmetime/spotify_ad_skipper.git
cd spotify_ad_skipper
pip install -r requirements.txt
python main.py --verbose

Code Style

  • Python 3.10+ type annotations (from __future__ import annotations)
  • NumPy-style docstrings
  • Clean separation of concerns — each module has a single responsibility
  • Logging via logging.getLogger(__name__) in every module

📄 License

This project is licensed under the MIT License — see the LICENSE file for details.


🙏 Acknowledgements

  • Built with psutil and pywin32
  • Inspired by the eternal struggle against Spotify's free-tier ads

Made with ❤️ for uninterrupted listening

⬆ Back to top

About

A lightweight Windows utility that silently detects and skips Spotify ads by monitoring window titles. Runs in the background with automatic ad detection + a global hotkey (Ctrl+Shift+R) to restart Spotify and resume playback — no focus steal, no disruption.

Topics

Resources

Contributing

Stars

Watchers

Forks

Contributors

Languages