{"_id":"@airplanegobrr/spotify-buddylist","name":"@airplanegobrr/spotify-buddylist","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@airplanegobrr/spotify-buddylist","version":"1.0.0","description":"Fetch the friend activity Spotify feed.","license":"Unlicense","author":{"name":"Val","url":"http://val.codejam.info"},"repository":{"type":"git","url":"git+https://github.com/airplanegobrr/spotify-buddylist.git"},"dependencies":{"node-fetch":"^2.6.1","otplib":"^12.0.1"},"devDependencies":{"standard":"^14.3.4"},"scripts":{"lint":"standard"},"_id":"@airplanegobrr/spotify-buddylist@1.0.0","bugs":{"url":"https://github.com/airplanegobrr/spotify-buddylist/issues"},"homepage":"https://github.com/airplanegobrr/spotify-buddylist#readme","_integrity":"sha512-Ig2HwtADZIbj7yO4ar9FBlgiE8S0I74rSDc1WltfZF8UZr8DaFmAiVnmzljyj/EGZKn0YAAr4eC3mRwtAOLLQA==","_resolved":"C:\\Users\\AIRPLA~1\\AppData\\Local\\Temp\\e53da603066575000e2b07c4ff086c94\\airplanegobrr-spotify-buddylist-1.0.0.tgz","_from":"file:airplanegobrr-spotify-buddylist-1.0.0.tgz","_nodeVersion":"20.18.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-Ig2HwtADZIbj7yO4ar9FBlgiE8S0I74rSDc1WltfZF8UZr8DaFmAiVnmzljyj/EGZKn0YAAr4eC3mRwtAOLLQA==","shasum":"a96d58923a76e3b215c83634c876453008767cc1","tarball":"https://registry.npmjs.org/@airplanegobrr/spotify-buddylist/-/spotify-buddylist-1.0.0.tgz","fileCount":3,"unpackedSize":11926,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDM8ki/ixFwmUW2T3ZTKSheIklFAXw6/5lamgnpTgfyOgIhAKVotzAEWj9x4zmothYDx0J+kuObekkQ4Ur5vXVvODQQ"}]},"_npmUser":{"name":"airplanegobrr","email":"airplanegobrrfeedback@gmail.com"},"directories":{},"maintainers":[{"name":"airplanegobrr","email":"airplanegobrrfeedback@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/spotify-buddylist_1.0.0_1746079233619_0.3932946944669855"},"_hasShrinkwrap":false}},"time":{"created":"2025-05-01T06:00:33.492Z","1.0.0":"2025-05-01T06:00:33.853Z","modified":"2025-05-01T06:00:34.229Z"},"maintainers":[{"name":"airplanegobrr","email":"airplanegobrrfeedback@gmail.com"}],"description":"Fetch the friend activity Spotify feed.","homepage":"https://github.com/airplanegobrr/spotify-buddylist#readme","repository":{"type":"git","url":"git+https://github.com/airplanegobrr/spotify-buddylist.git"},"author":{"name":"Val","url":"http://val.codejam.info"},"bugs":{"url":"https://github.com/airplanegobrr/spotify-buddylist/issues"},"license":"Unlicense","readme":"# spotify-buddylist [![npm version](http://img.shields.io/npm/v/spotify-buddylist.svg?style=flat-square)](https://www.npmjs.org/package/spotify-buddylist)\r\n\r\n> Fetch the friend activity Spotify feed.\r\n\r\n**Note:** don't know how to code? Check the [extra info](#dont-know-how-to-code)\r\nat the bottom!\r\n\r\n## Overview\r\n\r\nThe [Spotify API](https://developer.spotify.com/documentation/web-api/)\r\ndoesn't include a way to fetch the friend activity feed that's\r\navailable on the right of the desktop app.\r\n\r\nThere's an [issue on the spotify/web-api repository](https://github.com/spotify/web-api/issues/83)\r\nabout that, where a number of people request access to this endpoint\r\nsince 2015, but it was closed this summer 2020 without any plan to give\r\naccess to this feature through the official API.\r\n\r\nBecause I want to fetch this data and I don't like being told no, this\r\nrepo is a wrapper around the unofficial API that the app calls to fetch\r\nthe friend activity feed.\r\n\r\nSince the calls are pretty trivial, it's mostly there for public\r\ndocumentation purpose rather than to really be used as a library, but I\r\nstill made it available on npm in case you quickly want to put together\r\nsomething with this.\r\n\r\nThe only dependency is [node-fetch](https://github.com/node-fetch/node-fetch)\r\nto make HTTP requests.\r\n\r\n## Usage\r\n\r\nTo use this API, you need to get a web player access token, not a\r\nregular API access token, so you can't use the official API way of\r\nlogging in, getting and refreshing tokens.\r\n\r\nThe good news is that if you don't mind logging in on the web player and\r\nrefreshing a value in your code once a year, it's actually quite easier\r\nthan the official OAuth way. More on that [below](#sp_dc-cookie).\r\n\r\n```js\r\nconst buddyList = require('spotify-buddylist')\r\n\r\nasync function main () {\r\n  const spDcCookie = 'put your cookie here'\r\n\r\n  const { accessToken } = await buddyList.getWebAccessToken(spDcCookie)\r\n  const friendActivity = await buddyList.getFriendActivity(accessToken)\r\n\r\n  console.log(friendActivity)\r\n}\r\n\r\nmain()\r\n```\r\n\r\nThe output looks like:\r\n\r\n```json\r\n{\r\n  \"friends\": [\r\n    {\r\n      \"timestamp\": 1600773735000,\r\n      \"user\": {\r\n        \"uri\": \"spotify:user:shaktirockgym\",\r\n        \"name\": \"shaktirockgym\"\r\n      },\r\n      \"track\": {\r\n        \"uri\": \"spotify:track:51xHvAUYQfhY29GcGlBM0n\",\r\n        \"name\": \"Piano Sonata No. 16 in C Major, K. 545 \\\"Sonata facile\\\": 1. Allegro\",\r\n        \"imageUrl\": \"http://i.scdn.co/image/ab67616d0000b273bf4b533ee6e9634a6fcd8882\",\r\n        \"album\": {\r\n          \"uri\": \"spotify:album:1XORY4rQNhqkZxTze6Px90\",\r\n          \"name\": \"Piano Book (Deluxe Edition)\"\r\n        },\r\n        \"artist\": {\r\n          \"uri\": \"spotify:artist:4NJhFmfw43RLBLjQvxDuRS\",\r\n          \"name\": \"Wolfgang Amadeus Mozart\"\r\n        },\r\n        \"context\": {\r\n          \"uri\": \"spotify:user:spotify:playlist:37i9dQZF1E4riV8HyBkA7r\",\r\n          \"name\": \"Wolfgang Amadeus Mozart Radio\",\r\n          \"index\": 0\r\n        }\r\n      }\r\n    }\r\n  ]\r\n}\r\n```\r\n\r\n## `sp_dc` cookie\r\n\r\nThis is the only value that you need for this to work. After you login\r\non the [web player] (which I don't automate because reCAPTCHA), you get\r\na bunch of cookies, including one named `sp_dc`.\r\n\r\n[web player]: https://open.spotify.com/\r\n\r\nSeems like it's valid for one year, and with just that value you can\r\ncall anytime an endpoint that gives you a refreshed, elevated API access\r\ntoken, that, unlike the official API ones, will let you query the\r\nundocumented endpoint that retrieves the friend activity.\r\n\r\n## Usage with spotify-web-api-node\r\n\r\nYou might already be using the [spotify-web-api-node](https://github.com/thelinmichael/spotify-web-api-node)\r\npackage to use the official API. For convenience, I included a method to\r\nwrap it to include the `getWebAccessToken` and `getFriendActivity`\r\nmethods on it.\r\n\r\nUsing it that way, you can leverage the same elevated token for all the\r\nofficial API requests as well.\r\n\r\n```js\r\nconst SpotifyWebApi = require('spotify-web-api-node')\r\nconst buddyList = require('spotify-buddylist')\r\n\r\nconst api = buddyList.wrapWebApi(new SpotifyWebApi({ spDcCookie }))\r\n\r\nconst tokenResponse = await api.getWebAccessToken()\r\napi.setAccessToken(tokenResponse.body.accessToken)\r\n\r\nconst friendActivityResponse = await api.getFriendActivity()\r\nconst friendActivity = friendActivityResponse.body\r\n```\r\n\r\nShould your script run more than the token response's\r\n`accessTokenExpirationTimestampMs` (currently an hour), I would suggest\r\nimplementing token refresh logic which is just calling\r\n`getWebAccessToken` and `setAccessToken` again like above.\r\n\r\n## Don't know how to code?\r\n\r\nIf the documentation above doesn't make much sense to you, here's a\r\ncouple extra information you might find useful. 🙏\r\n\r\nBecause spotify-buddylist is a library, it's meant to be used by *other\r\nprograms*, and it doesn't makes any assumption on how it's going to be\r\nused. You're free to *code* a program that automatically populates\r\nanother playlist, sends you a notification when a specific friend plays\r\na specific song, feeds an online spreadsheet, or just appends to a local\r\nfile.\r\n\r\nBut don't worry, if you don't know how to code, you can still use the\r\n[example](example.js) that just displays the data when you run it. The\r\nfollowing steps will show you how to do that.\r\n\r\n### Installing\r\n\r\nBecause this library is built with [Node.js](https://nodejs.org/),\r\nyou'll need to install it first.\r\n\r\nThen, [download the archive for this repository](https://github.com/valeriangalliat/spotify-buddylist/archive/refs/heads/master.zip)\r\nand extract it.\r\n\r\nOpen a terminal, go in the spotify-buddylist directory that you just\r\nextracted, and run:\r\n\r\n```sh\r\nnpm install\r\n```\r\n\r\nThis will install the extra dependencies needed for the program to run.\r\n\r\n### Fetching the cookie\r\n\r\nThen you'll need to grab your `sp_dc` cookie from Spotify. This is a\r\nrequirement because Spotify doesn't allow third-party apps to get the\r\nfriend activity feed, so this cookie allows us to pretend that we're the\r\nSpotify app itself to get access to that data.\r\n\r\nFor that, login on the [web player] and open your browser's web\r\ndeveloper tools. It's usually in \"settings\", \"more tools\", \"developer\r\ntools\". In that pane, go in \"application\", \"storage\", \"cookies\",\r\n`https://open.spotify.com` (or something close to that depending on your\r\nbrowser).\r\n\r\nYou'll find a cookie named `sp_dc`. Copy its value.\r\n\r\n### Running the example\r\n\r\nIn the spotify-buddylist directory, open `example.js` with any text\r\neditor, and paste the cookie value in place of the text \"put your cookie\r\nhere\".\r\n\r\nNow, you can run the following command to execute the script:\r\n\r\n```sh\r\nnode example.js\r\n```\r\n\r\nThis will display the JSON response from Spotify (once).\r\n\r\nIf you want to run it periodically, you can uncomment the last line of\r\nthe file (remove the `//` from the beginning of the line and save the\r\nfile) and run the above command again. Now the script will run\r\nindefinitely, fetching new data every minute and appending it to the\r\nterminal output.\r\n\r\nThat should be enough to get you started! 🎉\r\n\r\nIf you want to do more things with that, you might want to learn a\r\nlittle bit of JavaScript. Programming is powerful, and will allow you to\r\ndo the things that *you* want to do with your computer, instead of being\r\nlimited to the things that someone else decided that you should be able\r\nto do. Enjoy!\r\n","readmeFilename":"README.md","_rev":"1-6c7fec106fd097fc7a0dad105ebc235c"}