Spotify Preview Finder

A Flutter package to search Spotify tracks, scrape 30-second preview URLs (bypassing the deprecated preview_url Web API limitation), and play them instantly.


Why Spotify Preview Finder?

Spotify recently deprecated the public Web API's preview_url field, returning null for all authenticated track queries. However, Spotify’s public web pages still play 30-second audio previews for anonymous visitors.

This package replicates that behavior by:

  1. Searching the Spotify Web API using standard client credentials to retrieve track metadata and public track URLs (e.g., https://open.spotify.com/track/{id}).
  2. Converting public track URLs into Spotify Embed Player URLs (https://open.spotify.com/embed/track/{id}). This forces Spotify to pre-render the full page HTML (with JSON metadata) instead of returning a light client-side Web Player skeleton.
  3. Scanning the pre-rendered HTML response via optimized Regular Expressions to extract the raw 30-second preview MP3 stream URLs hosted on p.scdn.co.
  4. Providing a controller class (SpotifyPreviewPlayer) and a premium, out-of-the-box Spotify-themed widget (SpotifyPreviewPlayerWidget) to easily play them.

Getting Started

1. Retrieve Spotify Developer Credentials

To search tracks, you need standard client credentials from Spotify:

  1. Go to the Spotify Developer Dashboard.
  2. Log in and click Create App.
  3. Fill in the app details, and retrieve your Client ID and Client Secret.

2. Add Dependency

Add this to your Flutter project's pubspec.yaml file:

dependencies:
  flutter:
    sdk: flutter
  spotify_preview_finder:
    path: path/to/spotify_preview_finder # Or standard version if fetched from pub.dev

Usage

1. Fetching and Extracting Previews

Here is how to get an access token, search for a song, and get its metadata and preview URLs:

import 'package:spotify_preview_finder/spotify_preview_finder.dart';

void main() async {
  // 1. Get client credentials token
  final accessToken = await SpotifyPreviewFinder.getAccessToken(
    clientId: 'YOUR_CLIENT_ID',
    clientSecret: 'YOUR_CLIENT_SECRET',
  );

  // 2. Search for a track and automatically scrape its preview URL
  final List<SpotifyTrack> tracks = await SpotifyPreviewFinder.searchAndGetPreviews(
    songName: 'Blinding Lights',
    artist: 'The Weeknd', // Optional
    accessToken: accessToken,
    limit: 5, // Optional (default is 5)
  );

  for (var track in tracks) {
    print('Track Name: ${track.name}');
    print('Scraped Preview MP3 URL: ${track.previewUrls.firstOrNull}');
  }
}

2. Custom Audio Controller (SpotifyPreviewPlayer)

If you want to build a custom player UI, you can use the SpotifyPreviewPlayer controller:

final player = SpotifyPreviewPlayer();

// Start playback
await player.play(track.previewUrls.first);

// Pause playback
await player.pause();

// Resume playback
await player.resume();

// Stop and reset position
await player.stop();

// Listen to player state changes
player.onStateChanged.listen((SpotifyPreviewState state) {
  print('Player State: $state'); // e.g. loading, playing, paused, completed
});

// Listen to playback positions (for sliders/progress bars)
player.onPositionChanged.listen((Duration position) {
  print('Position: ${position.inSeconds}s');
});

// Always dispose the player when done
player.dispose();

3. Out-of-the-Box Player Widget (SpotifyPreviewPlayerWidget)

For plug-and-play Spotify-style UI elements, use the pre-built SpotifyPreviewPlayerWidget. It contains track details, album artwork, interactive progress sliders, and control buttons out of the box.

import 'package:flutter/material.dart';
import 'package:spotify_preview_finder/spotify_preview_finder.dart';

class TrackPlayerCard extends StatelessWidget {
  final SpotifyTrack track;
  final SpotifyPreviewPlayer sharedPlayer;

  const TrackPlayerCard({
    Key? key,
    required this.track,
    required this.sharedPlayer,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SpotifyPreviewPlayerWidget(
      track: track,
      player: sharedPlayer, // Share player to ensure only one track plays at a time
      accentColor: const Color(0xFF1DB954), // Customize color (defaults to Spotify Green)
    );
  }
}

Note

Coordinated Playback & VBR Duration Overriding:

  • Coordinated Playback: By passing a single sharedPlayer instance to a list of widgets, playing a new track will automatically stop the previously playing track. The widget handles filtering internally so only the actively playing card displays progress while others stay reset at 00:00.
  • VBR Duration Correction: Spotify preview streams use Variable Bitrate (VBR) encoding. This causes standard hardware decoders (such as ExoPlayer on Android) to incorrectly read metadata and report durations under 30 seconds (e.g. 17s). SpotifyPreviewPlayerWidget automatically intercepts and overrides the duration display to 30 seconds for standard previews to ensure smooth, synchronized slider progress.

License

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

Disclaimer

This package resolves preview URLs by scraping Spotify's public web elements. While highly efficient, this method depends on Spotify's public HTML formatting. If Spotify modifies its public page structure or URL formatting, scraping might break. Use this package responsibly and in accordance with Spotify's terms of service.

Libraries

spotify_preview_finder
Support for doing something awesome.