The Ops Community ⚙️

Jhon Mu
Jhon Mu

Posted on

Auto-Save Your Discover Weekly with Spotify Bot

If you’re like me, your Discover Weekly playlist is one of your favorite parts of Monday. That perfect blend of new music, artists you’ve never heard of, and the occasional gem you end up obsessing over for weeks.

But here's the catch: it disappears every week. If you don’t save that one track you loved, it’s gone — lost to the Spotify void forever.

That got me thinking:

“Why isn’t there an easy way to automatically save Discover Weekly before it refreshes?”

So I decided to build it myself. A small, lightweight Node.js bot that runs once a week, grabs my Discover Weekly, and saves it into a dated playlist for easy reference later.

And you can build it too — in under 100 lines of JavaScript.

What You’ll Need

To follow along, here’s what you’ll need:

  • A Spotify Developer Account
  • A Spotify App (to get your Client ID & Secret)
  • Node.js installed on your machine
  • A bit of familiarity with JavaScript and APIs
  • A free Spotify account (although premium unlocks more features)

Step 1: Set Up OAuth with Spotify

First, create your project:

mkdir discover-weekly-archiver
cd discover-weekly-archiver
npm init -y
npm install express axios dotenv querystring open
Enter fullscreen mode Exit fullscreen mode

Create a .env file with your credentials:

SPOTIFY_CLIENT_ID=your_client_id
SPOTIFY_CLIENT_SECRET=your_client_secret
SPOTIFY_REDIRECT_URI=http://localhost:8888/callback

Enter fullscreen mode Exit fullscreen mode

Then create your server:

// auth-server.js
require('dotenv').config();
const express = require('express');
const axios = require('axios');
const querystring = require('querystring');
const open = require('open');

const app = express();
const port = 8888;

const SCOPES = [
  'playlist-read-private',
  'playlist-modify-private',
  'playlist-modify-public',
  'user-read-email',
].join(' ');

app.get('/login', (req, res) => {
  const params = querystring.stringify({
    response_type: 'code',
    client_id: process.env.SPOTIFY_CLIENT_ID,
    scope: SCOPES,
    redirect_uri: process.env.SPOTIFY_REDIRECT_URI,
  });

  res.redirect(`https://accounts.spotify.com/authorize?${params}`);
});

app.get('/callback', async (req, res) => {
  const code = req.query.code;

  const tokenResponse = await axios.post(
    'https://accounts.spotify.com/api/token',
    querystring.stringify({
      grant_type: 'authorization_code',
      code,
      redirect_uri: process.env.SPOTIFY_REDIRECT_URI,
    }),
    {
      headers: {
        Authorization:
          'Basic ' +
          Buffer.from(
            `${process.env.SPOTIFY_CLIENT_ID}:${process.env.SPOTIFY_CLIENT_SECRET}`
          ).toString('base64'),
        'Content-Type': 'application/x-www-form-urlencoded',
      },
    }
  );

  const { access_token, refresh_token } = tokenResponse.data;

  console.log('Access Token:', access_token);
  console.log('Refresh Token:', refresh_token);
  res.send('✅ Authenticated! You can now run your script.');
});

app.listen(port, () => {
  console.log(`Visit http://localhost:${port}/login to authenticate`);
  open(`http://localhost:${port}/login`);
});
Enter fullscreen mode Exit fullscreen mode

Run it with:

node auth-server.js

Enter fullscreen mode Exit fullscreen mode

This step gives you an access token and refresh token — copy and store them securely.

Step 2: Find Your Discover Weekly Playlist

APK Spotify Premium assigns Discover Weekly the same ID for everyone, but it’s in a user-specific context. The easiest way to find it is to fetch your playlists and search by name.

Here’s how:

async function getDiscoverWeeklyPlaylist(token) {
  const res = await axios.get('https://api.spotify.com/v1/me/playlists?limit=50', {
    headers: { Authorization: `Bearer ${token}` },
  });

  const playlists = res.data.items;
  const discover = playlists.find(p => p.name === 'Discover Weekly');

  return discover;
}

Enter fullscreen mode Exit fullscreen mode

Once you have the playlist object, grab its id and fetch the tracks:

async function getPlaylistTracks(token, playlistId) {
  const res = await axios.get(
    `https://api.spotify.com/v1/playlists/${playlistId}/tracks`,
    {
      headers: { Authorization: `Bearer ${token}` },
    }
  );

  return res.data.items.map(item => item.track.uri);
}

Enter fullscreen mode Exit fullscreen mode

Step 3: Create a New Archive Playlist

Now we’ll create a new playlist each week with the current date.

async function createArchivePlaylist(token, userId) {
  const today = new Date().toISOString().split('T')[0];

  const res = await axios.post(
    `https://api.spotify.com/v1/users/${userId}/playlists`,
    {
      name: `📦 Discover Weekly – ${today}`,
      description: 'Auto-archived Discover Weekly tracks',
      public: false,
    },
    {
      headers: {
        Authorization: `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
    }
  );

  return res.data.id;
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Add Tracks to the Archive

Once we have the new playlist and the track URIs, just add them:

async function addTracks(token, playlistId, uris) {
  await axios.post(
    `https://api.spotify.com/v1/playlists/${playlistId}/tracks`,
    { uris },
    {
      headers: {
        Authorization: `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
    }
  );
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Wrap It All Up

Here’s the full flow in one function:

async function archiveDiscoverWeekly(token) {
  const me = await axios.get('https://api.spotify.com/v1/me', {
    headers: { Authorization: `Bearer ${token}` },
  });

  const userId = me.data.id;

  const discover = await getDiscoverWeeklyPlaylist(token);
  if (!discover) {
    console.error('Could not find Discover Weekly!');
    return;
  }

  const uris = await getPlaylistTracks(token, discover.id);

  const newPlaylistId = await createArchivePlaylist(token, userId);
  await addTracks(token, newPlaylistId, uris);

  console.log(`✅ Archived ${uris.length} tracks from Discover Weekly!`);
}
Enter fullscreen mode Exit fullscreen mode

Bonus: Automate with a Cron Job

Want this to run automatically every week? Use a cron job or set up a task with node-cron.

Install the package:

npm install node-cron
Enter fullscreen mode Exit fullscreen mode

Add this to your script:

const cron = require('node-cron');

cron.schedule('0 9 * * MON', () => {
  archiveDiscoverWeekly('your_access_token_here');
});
Enter fullscreen mode Exit fullscreen mode

Now it runs every Monday at 9am.

Final Thoughts

This might be a simple project, but it solves a real, everyday problem.

I didn’t want to build something flashy or complex — just a practical utility that lets me hold on to the music I love before Spotify wipes it clean each week.

It’s lightweight, fast, and it works.

If you’re like me and Discover Weekly is a key part of your weekly music discovery, I highly recommend setting this up. You’ll thank yourself months from now when you rediscover that one song you forgot existed.

Want to Take It Further?

  • Auto-post your weekly archive to Discord or Slack
  • Store archived track data in a database for future analysis
  • Build a web dashboard to browse your weekly archives
  • Analyze track features over time to see how your taste evolves

Top comments (0)