{"id":18712197,"url":"https://github.com/spotify/spotify-web-api-ts-sdk","last_synced_at":"2025-10-25T01:35:05.638Z","repository":{"id":170930178,"uuid":"627833721","full_name":"spotify/spotify-web-api-ts-sdk","owner":"spotify","description":"A Typescript SDK for the Spotify Web API with types for returned data.","archived":false,"fork":false,"pushed_at":"2024-08-20T17:05:07.000Z","size":752,"stargazers_count":413,"open_issues_count":50,"forks_count":81,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-03-31T22:21:39.939Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spotify.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-14T09:52:22.000Z","updated_at":"2025-03-31T19:04:21.000Z","dependencies_parsed_at":"2024-06-18T19:59:39.857Z","dependency_job_id":"77234f3e-e62c-4576-be8a-c6e6ca711a3c","html_url":"https://github.com/spotify/spotify-web-api-ts-sdk","commit_stats":null,"previous_names":["spotify/spotify-web-api-ts-sdk"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spotify%2Fspotify-web-api-ts-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spotify%2Fspotify-web-api-ts-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spotify%2Fspotify-web-api-ts-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spotify%2Fspotify-web-api-ts-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spotify","download_url":"https://codeload.github.com/spotify/spotify-web-api-ts-sdk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247744335,"owners_count":20988783,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T12:40:54.038Z","updated_at":"2025-10-25T01:35:05.620Z","avatar_url":"https://github.com/spotify.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# Spotify Web API SDK - TypeScript\n\nThis is a JavaScript/TypeScript SDK for the [Spotify Web API](https://developer.spotify.com/web-api/).\n\n## Requirements\n\nBecause this SDK uses `fetch` both in Node and the Browser, and ESM, we require the following:\n\n- Node 18.0.0 or higher\n- A modern, version infinite, browser\n\nThe package contains both an ESM and CommonJS build, so you can use it in both Node and the Browser.\n\n## Using this in your project\n\n```bash\nnpm install @spotify/web-api-ts-sdk\n```\n\n## Running the example app\n\nFirst install the dependencies:\n\n```bash\nnpm install\n```\n\nCreate a `.env` file in the example directory with your `client_id` and redirect url:\n\n```bash .env\nVITE_SPOTIFY_CLIENT_ID=your_spotify_client_id_for_tests\nVITE_REDIRECT_TARGET=http://localhost:3000\n```\n\nTo run the app:\n\n```bash\nnpm run start\n```\n\n### Creating a client instance\n\nCreating an instance of the SDK is easy, and can be done in a number of ways depending on which form of authentication you want to use.\n\n```js\nimport { SpotifyApi } from '@spotify/web-api-ts-sdk';\n\n// Choose one of the following:\nconst sdk = SpotifyApi.withUserAuthorization(\"client-id\", \"https://localhost:3000\", [\"scope1\", \"scope2\"]);\nconst sdk = SpotifyApi.withClientCredentials(\"client-id\", \"secret\", [\"scope1\", \"scope2\"]);\n```\n\nEach of these factory methods will return a `SpotifyApi` instance, which you can use to make requests to the Spotify Web API.\n\nOnce you have an authenticated instance of the SDK, you can make requests to the Spotify Web API by using the methods exposed on the client instance of the API. Types are embedded in the package, so if you're using Visual Studio Code or other compatible IDEs, you should get intellisense and type checking by default.\n\n```js\nconst items = await sdk.search(\"The Beatles\", [\"artist\"]);\n\nconsole.table(items.artists.items.map((item) =\u003e ({\n    name: item.name,\n    followers: item.followers.total,\n    popularity: item.popularity,\n})));\n```\n\n### Authentication Methods\n\n- Authorization Code Flow with PKCE\n- Client Credentials Flow\n- Mixed Server and Client Side Authentication\n\nWe do auto-token refresh when expired and a refresh token is available.\n\n### Picking an Authentication Method\n\nIf you're building a browser based application, you should use Authorization Code Flow with PKCE. This is the most secure way to authenticate your users and handles the redirection from your app to Spotify and back. Your server side code will not have access to the Spotify API with user access scopes, but you can use the SDK to perform client side requests with the users access token.\n\nCalling any of the methods on the SDK will automatically perform any redirects/refreshes that are necessary.\n\n```js\nconst sdk = SpotifyApi.withUserAuthorization(\"client-id\", \"https://localhost:3000\", [\"scope1\", \"scope2\"]);\nconst user = await sdk.currentUser.profile()\n```\n\n\nIf you're building a server side application, you should use Client Credentials Flow, and is the correct choice when you have both your Client ID and Client Secret available. This flow is not available in the browser (as you should not embed your Client Secret in Client Side web applications), so should only be used from Node.js.\n\nMixed Server and Client Side Authentication is a special case, and is covered in the section below. This is useful if you want to perform requests with a users access token from your server side code.\n\n### Mixed Server and Client Side Authentication\n\nThere's capabilities in the client if you want to interact with Spotify from your Node.js server, but perform a client side Authorization Code Flow with PKCE.\nYou might want to do this if you want your server side SDK instance to be authorized \"as a specific user\" to interact with user data.\n\nYou'll need to do three things.\n\n1. Perform Authorization Code Flow with PKCE using some special helper functions\n2. Expose a URL from your Node.js application that accepts a token post-back\n3. Initilise an instance of the SDK with the posted-back token\n\nSetup:\n\n*Client Side*\n```js\nSpotifyApi.performUserAuthorization(\"client-id\", \"https://localhost:3000\", [\"scope1\", \"scope2\"], \"https://your-backend-server.com/accept-user-token\");\n// Alternatively if you want to perform your own custom post-back\nSpotifyApi.performUserAuthorization(\"client-id\", \"https://localhost:3000\", [\"scope1\", \"scope2\"], (accessToken) =\u003e { /* do postback here */ });\n```\n\nThese functions will work as usual, triggering a client side redirect to grant permissions, along with verifying the response and performing token exchange.\n\n*Server Side*\n```js\nconst { SpotifyApi } = require(\"@spotify/web-api-ts-sdk\");\n\nconst express = require('express');\nconst bodyParser = require('body-parser'); \nconst app = express();\n \napp.use(bodyParser.json());\napp.use(bodyParser.urlencoded({ extended: false }));\n\nlet sdk;\n\napp.post('/accept-user-token', (req, res) =\u003e {\n    let data = req.body;\n    sdk = SpotifyApi.withAccessToken(\"client-id\", data); // SDK now authenticated as client-side user\n}); \n \napp.listen(3000, () =\u003e {\n  console.log('Example app listening on port 3000!')\n});\n```\n\n[Check out our blog post for more examples using ES Modules or CommonJS](https://developer.spotify.com/blog/2023-07-03-typescript-sdk)\n\n### Extensibility\n\nAll of the constructors support a configuration object that lets you override the default behavior of the SDK.\n\nOur defaults look like this, and each of the properties is optional, and can be overridden.\n\n```ts\nconst defaultConfig: SdkConfiguration = {\n    fetch: (req: RequestInfo | URL, init: RequestInit | undefined) =\u003e fetch(req, init),\n    beforeRequest: (_: string, __: RequestInit) =\u003e { },\n    afterRequest: (_: string, __: RequestInit, ___: Response) =\u003e { },\n    deserializer: new DefaultResponseDeserializer(),\n    responseValidator: new DefaultResponseValidator(),\n    errorHandler: new NoOpErrorHandler(),\n    redirectionStrategy: new DocumentLocationRedirectionStrategy(),\n    cachingStrategy: isBrowser\n        ? new LocalStorageCachingStrategy()\n        : new InMemoryCachingStrategy()\n};\n```\n\nAs a general rule, this options should be overridden when you create your instance of the client, and you probably won't have to change any of them unless you have some very specific requirements.\n\nYou can provide the options like this, to any of the constructors or static initilisation methods:\n\n```js\nconst opts = {\n    fetch: (req, init) =\u003e {\n        console.log(\"Called via my custom fetch!\");\n        return fetch(req, init);\n    }\n}\n\nconst sdk = SpotifyApi.withUserAuthorization(\"client-id\", \"https://callback\", [\"scope1\"], opts);\n```\n\nAll the below examples are in TypeScript, but the same method signatures all apply to JavaScript - just without the Type information.\n\n### Extensibility - fetch\n\nYou can override the default Fetch implementation by passing in a function that takes a `RequestInfo` and `RequestInit` and returns a `Promise\u003cResponse\u003e`. By default, we use the browser and nodes built in `fetch` implementation.\n\n```js\nconst opts = {\n    fetch: (req, init) =\u003e {\n        // Do something with the request\n        return fetch(req, init);\n    }\n}\n```\n\n### Extensibility - beforeRequest and afterRequest\n\nYou can override the default `beforeRequest` and `afterRequest` callbacks by passing in functions that take a `RequestInfo` and `RequestInit` and return nothing. By default, we do nothing.\n\nYou can use these functions to implement custom instrumentation, logging, or other functionality.\n\n```js\nconst opts = {\n    beforeRequest: (req, init) =\u003e {\n        console.log(\"Called before the request is made\");\n    },\n    afterRequest: (req, init, res) =\u003e {\n        console.log(\"Called after the request is made\");\n    }\n}\n```\n\n### Extensibility - deserializer\n\nYou can override the default deserializer by passing in a class that implements the `IResponseDeserializer` interface. By default, we use the `DefaultResponseDeserializer` class.\n\nTo implement your own, you need to provide an object with the following method signature:\n\n```ts\nasync deserialize\u003cTReturnType\u003e(response: Response): Promise\u003cTReturnType\u003e {\n    // Implement your custom deserialization logic here\n}\n```\n\nYou'll probably never need to do this unless you feel the need to add custom logging around deserialization behaviour or wish to customise the default objects returned during serialization failures.\n\n### Extensibility - responseValidator\n\nYou can override the default response validator by passing in a class that implements the `IValidateResponses` interface. By default, we use the `DefaultResponseValidator` class.\n\nOur default impelementation validates the following:\n\n- The response status code is in the 200 range\n- Errors are thrown for 400 and 500 range status codes\n- Non-200 response codes throw errors with the API response body inside of them\n\nIf you need to customise this behaviour, replace the implementation like this:\n\n```ts\nexport default class MyResponseValidator implements IValidateResponses {\n    public async validateResponse(response: Response): Promise\u003cvoid\u003e {\n        // Something here\n    }\n}\n```\n\n### Extensibility - errorHandler\n\nYou can override the default error handler by passing in a class that implements the `IHandleErrors` interface. By default, we use the `NoOpErrorHandler` class which... does nothing!\n\nIf you need to customise this behaviour, replace the implementation like this:\n\n```ts\nexport default class MyErrorHandler implements IHandleErrors {\n    public async handleErrors(error: any): Promise\u003cboolean\u003e {\n        return false;\n    }\n}\n```\n\nIf you return `true` from your error handler, the SDK will not throw an error, and treat it as handleed, returning null from the request that triggered it. Returning false will re-throw the original error after your handler has run.\n\n### Extensibility - redirectionStrategy\n\nYou can override the default redirection strategy by passing in a class that implements the `IRedirect` interface. By default, we use the `DocumentLocationRedirectionStrategy` class.\n\n```ts\nexport default class DocumentLocationRedirectionStrategy implements IRedirectionStrategy {\n    public async redirect(targetUrl: string | URL): Promise\u003cvoid\u003e {\n        document.location = targetUrl.toString();\n    }\n\n    public async onReturnFromRedirect(): Promise\u003cvoid\u003e {\n    }\n}\n```\n\nYou might want to override this behaviour if you use a client side framework like React or Vue and you need to record some state, or trigger some operation before the redirect for oAuth / token exchange happens. For example - you might want to add something to localStorage that you can read back when the user returns to the application.\n\n### Extensibility - cachingStrategy\n\nYou can override the default caching strategy by passing in a class that implements the `ICache` interface. By default, we use the `LocalStorageCachingStrategy` class.\n\n```ts\ninterface ICachingStrategy {\n    getOrCreate\u003cT\u003e(cacheKey: string, createFunction: () =\u003e Promise\u003cT \u0026 ICachable \u0026 object\u003e): Promise\u003cT \u0026 ICachable\u003e;\n    get\u003cT\u003e(cacheKey: string): T \u0026 ICachable | null;\n    setCacheItem\u003cT\u003e(cacheKey: string, item: T \u0026 ICachable): void;\n    remove(cacheKey: string): void;\n}\n```\n\nWe provide a default browser (localStorage) caching strategy and (TODO) a node in-memory caching strategy.\n\n## Running the tests\n\nTo run the tests, you need to have a Spotify account.\n\nYou will need to create a new app in the Spotify Developer portal, and add a redirect URI of `http://localhost:3000`.\n\nYou will need to add the following environment variables:\n\n- `INTEGRATION_TESTS_REFRESH_TOKEN`\n- `INTEGRATION_TESTS_SPOTIFY_CLIENT_ID`\n- `INTEGRATION_TESTS_SPOTIFY_CLIENT_SECRET`\n\n`INTEGRATION_TESTS_REFRESH_TOKEN` is used to run integration tests in the scope of a *real user account*. This is required to test endpoints that require a user's authorization, such as `followPlaylist`. You need to make sure that your user has access to whichever Spotify app your client credentials and secret are for. You can obtain a refresh token by running the example app and authenticating.\n\nYou can run the tests with `npm run test`, or using a plugin like [Wallaby](https://wallabyjs.com/).\n\nWe support `dotenv`, so you can add these to a `.env` file in the root of the repository.\n\nTo run the embedded example app, you will need to add the following environment variables:\n\n- `VITE_SPOTIFY_CLIENT_ID`=the same value as set in INTEGRATION_TESTS_SPOTIFY_CLIENT_ID\n- `VITE_REDIRECT_TARGET`=http://localhost:3000\n\nFor the example app to work, this .env file needs to be in the ./example folder.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspotify%2Fspotify-web-api-ts-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspotify%2Fspotify-web-api-ts-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspotify%2Fspotify-web-api-ts-sdk/lists"}