Skip to main content

Extensions

Extensions are JavaScript files that run alongside Spotify's main code. They can add UI elements, modify behavior, integrate with external services, and more.

Extension Structure​

~/.config/spicetify/Extensions/   # Linux/macOS
%appdata%\spicetify\Extensions\ # Windows
├── myExtension.js
├── anotherExtension.js
└── ...

Extensions are single JavaScript files. For complex extensions with multiple files, use Spicetify Creator.

Getting Started​

Location​

Place your extension file in the Extensions folder:

PlatformPath
Windows%appdata%\spicetify\Extensions\
Linux / macOS~/.config/spicetify/Extensions/

Minimal Extension​

// myExtension.js
(function myExtension() {
// Wait for Spicetify to be ready
if (!Spicetify.Player || !Spicetify.Platform) {
setTimeout(myExtension, 100);
return;
}

console.log("My extension loaded!");

// Your code here
})();

Testing Your Extension​

  1. Save your file to the Extensions folder

  2. Enable it:

    spicetify config extensions myExtension.js
    spicetify apply
  3. Open DevTools in Spotify to see console output:

    • Windows/Linux: Ctrl + Shift + I
    • macOS: Cmd + Option + I

The Spicetify API​

Extensions access Spotify through the global Spicetify object. Key namespaces:

NamespacePurpose
Spicetify.PlayerPlayback control (play, pause, skip, volume)
Spicetify.PlatformCore platform APIs (history, library, playlists)
Spicetify.CosmosAsyncHTTP requests to Spotify's internal API
Spicetify.URIParse and create Spotify URIs
Spicetify.ReactReact instance for UI components
Spicetify.ReactDOMReactDOM for rendering
Spicetify.TopbarAdd buttons to the top bar
Spicetify.PlaybarAdd buttons to the player bar
Spicetify.ContextMenuAdd items to right-click menus

See the API Wrapper Reference for complete documentation.


Common Patterns​

Waiting for Spicetify​

Always wait for Spicetify to be ready before accessing its APIs:

(function init() {
if (!Spicetify.Player || !Spicetify.Platform) {
setTimeout(init, 100);
return;
}

main();
})();

function main() {
// Safe to use Spicetify here
}

Adding a Top Bar Button​

const button = new Spicetify.Topbar.Button(
"My Button",
`<svg>...</svg>`, // SVG icon
() => {
console.log("Button clicked!");
}
);

Adding a Context Menu Item​

new Spicetify.ContextMenu.Item(
"My Menu Item",
(uris) => {
console.log("Selected URIs:", uris);
},
(uris) => {
// Return true to show this item
return true;
},
`<svg>...</svg>` // Optional icon
).register();

Listening to Player Events​

Spicetify.Player.addEventListener("songchange", (event) => {
const track = Spicetify.Player.data?.item;
console.log("Now playing:", track?.name);
});

Making API Requests​

// GET request
const response = await Spicetify.CosmosAsync.get(
"https://api.spotify.com/v1/me/player"
);

// POST request
await Spicetify.CosmosAsync.post(
"https://api.spotify.com/v1/me/player/play",
{ uris: ["spotify:track:..."] }
);

Storing Data​

// Save
Spicetify.LocalStorage.set("myExtension:setting", "value");

// Load
const value = Spicetify.LocalStorage.get("myExtension:setting");

Showing Notifications​

Spicetify.showNotification("Hello from my extension!");

UI Development​

Using React​

Spicetify exposes React for building UI:

const { React, ReactDOM } = Spicetify;
const { useState, useEffect } = React;

function MyComponent() {
const [count, setCount] = useState(0);

return React.createElement("button", {
onClick: () => setCount(c => c + 1)
}, `Clicked ${count} times`);
}

Using Spotify's Components​

Access Spotify's internal React components:

const { Button, Toggle } = Spicetify.ReactComponent;

// Use in your components
React.createElement(Button, {
onClick: () => console.log("clicked")
}, "Click me");

Creating Modals​

Spicetify.PopupModal.display({
title: "My Modal",
content: React.createElement("div", null, "Hello!"),
});

Spicetify Creator​

For a better development experience with TypeScript, JSX, and hot reloading, use Spicetify Creator.

npx spicetify-creator

Benefits:

  • TypeScript support with full type definitions
  • JSX syntax (no manual React.createElement)
  • Hot reloading during development
  • Build tooling (bundling, minification)

Best Practices​

Performance​

  • Avoid polling. Use event listeners when possible
  • Debounce expensive operations
  • Clean up listeners when no longer needed

Error Handling​

try {
const data = await Spicetify.CosmosAsync.get("...");
} catch (error) {
console.error("Request failed:", error);
Spicetify.showNotification("Something went wrong", true);
}

Compatibility​

  • Test with both light and dark themes
  • Check for API existence before using (APIs can change between Spotify versions)
  • Use feature detection:
if (Spicetify.Topbar?.Button) {
// Safe to use
}

Naming​

  • Use a unique prefix for localStorage keys: myExtension:key
  • Use descriptive function and variable names

Publishing​

To share your extension:

  1. GitHub: Create a repository with your extension file(s) and installation instructions

  2. Marketplace: Submit to the Spicetify Marketplace for easy discovery and installation


Resources​