Developer Docs · v1

Build with your Suno library data.

Suno Explorer exports your library as a stable JSON format. Wire it up to spreadsheets, analytics, AI agents, custom dashboards, archival tools — anything you can imagine. Format, compression, and an AI-agent starter, all on one page.

Download extension Jump to format spec

01Get the data out

Open the extension's Data Management page. The Full Backup action emits a JSON file containing everything: clips, curation, downloads, playlists, settings. Two file formats:

Default

Compact (.compact.json)

Dictionary-encoded. ~89% smaller. Works in any tool that can call the decompress function below. Best for syncing, backups, large libraries.

For tooling

Uncompressed (.json)

Standard JSON. Larger but immediately readable. Best when wiring up external tools, scripts, or AI agents that need direct access.

In the Data Management UI, uncheck "Compact format" before exporting.

Stability commitment: Both formats carry _format and _version fields. Minor field additions don't bump the version. Breaking removals or renames bump the major version and are announced in advance. We aim for breaking changes to be rare.

02The format

Top-level shape of an uncompressed backup file:

{
  "_format": "suno-explorer-backup",
  "_version": 1,
  "exportedAt": "2026-05-17T...",
  "exportedBy": "Suno Explorer",

  "clips": [ /* Array of clip objects from Suno's API + extension fields */ ],
  "clipCount": 38421,

  "downloads": [ /* Per-clip download tracking */ ],
  "manualLinks": { /* clipId → parentClipId overrides */ },

  "playlists": {
    "explorer": { /* extension-created playlists */ },
    "suno":     { /* mirrored from Suno API */ }
  },

  "preferences": {
    "customNames": { /* baseTitle → display name */ },
    "customTags":  { /* clipId → { private: [], public: [] } */ },
    "customNotes": { /* clipId → { private: "", public: "" } */ },
    "visibility":  { /* clipId → boolean */ },
    "definitiveVersions": { /* baseTitle → { overall, vocals, instrumental } */ },
    "releaseStatus": { /* clipId → "released" | "wip" | "private" | ... */ },
    "externalLinks": { /* clipId → [{ url, platform }] */ },
    "hideUnliked":   { /* baseTitle → { enabled, enforcePublicly } */ },
    "customArt":     { /* baseTitle → URL */ },
    "disliked":      { /* clipId → boolean */ },
    "sampleClassifications": { /* clipId → classification */ }
  },

  "settings": { /* extension settings — grouping mode, etc. */ },
  "sampleLibraryMeta": { /* per-sample metadata */ }
}

Clip object — most-used fields

FieldTypeNotes
idstring (UUID)Suno clip ID. Stable across re-indexes.
titlestringSuno's title (may differ from custom name).
baseTitlestringNormalized title used for grouping versions of the same song.
audio_urlstringSuno CDN URL. Can expire — re-index to refresh.
image_url / image_large_urlstringCover art URLs (CDN).
created_atISO timestampWhen Suno generated the clip.
is_likedbooleanSuno's "heart" state.
major_model_versionstringe.g. "v5", "v4.5".
metadata.tagsstringComma-separated style tags.
metadata.promptstringLyrics (or instrumental prompt).
metadata.gpt_description_promptstring"Simple mode" description if used.
metadata.typestringe.g. "upload", "cover", "extend", "mashup".
metadata.durationnumberLength in seconds.
metadata.has_vocal / is_instrumentalbooleanSuno's flags. Often unreliable — see issues.
Parent-relationship fields: upsample_clip_id, edited_clip_id, source_clip_id, concat_clip_id, cover_clip_id, continue_clip_id, etc.string | nullUsed by lineage logic. See shared/core.js in the source.
projectobject | null{ id, name } — the Suno workspace this clip lives in. Null = default workspace.

03Working with the compact format

The compact format uses dictionary encoding — clip IDs become integer indices, repeated lyrics and tag sets are deduplicated, model names compress to single digits. ~89% smaller for typical libraries.

Decompress / compress functions

The full source of LibraryCompressor ships with the extension at shared/library-compressor.js. Copy it as-is, or fetch the canonical version below. Both compression and expansion are pure functions — no external dependencies.

// Browser / Node-compatible: fetch the canonical compressor source
// from the extension's installed location, OR copy shared/library-compressor.js
// directly out of the unpacked extension into your project.

// Usage:
//   const LibraryCompressor = require('./library-compressor.js');
//   const compactBackup = JSON.parse(fs.readFileSync('backup.compact.json'));
//   const fullBackup = LibraryCompressor.expand(compactBackup);
//   const clips = fullBackup.clips;
//   console.log(`Loaded ${clips.length} clips`);

Minimal Node.js example reading a compact backup, decompressing, filtering for liked instrumentals:

const fs = require('fs');
const LibraryCompressor = require('./library-compressor.js');

const raw = JSON.parse(fs.readFileSync('suno-explorer-backup.compact.json'));
if (raw._format !== 'suno-explorer-compact') {
  throw new Error('Not a Suno Explorer compact backup');
}

const full = LibraryCompressor.expand(raw);

const likedInstrumentals = full.clips.filter(c =>
  c.is_liked &&
  (c.metadata?.is_instrumental || !c.metadata?.prompt?.trim())
);

console.log(`${likedInstrumentals.length} liked instrumentals`);
likedInstrumentals.slice(0, 10).forEach(c => {
  console.log(`  - ${c.title}  [${c.metadata?.tags || ''}]`);
});

04AI agent starter

Drop this prompt into Claude, Cursor, Codex, or any coding agent to bootstrap a project that reads, analyzes, or transforms a Suno Explorer backup. Adapt the goals at the bottom to whatever you're building.

You're helping me build a tool that works with my Suno music library data.

The data is exported from the Suno Explorer Chrome extension as a JSON file
(format documented at https://suno-explorer.com/dev). Two flavors:

  - "suno-explorer-backup"  (uncompressed, human-readable)
  - "suno-explorer-compact" (dictionary-encoded, ~89% smaller — needs the
    LibraryCompressor.expand() function to read; source at
    shared/library-compressor.js in the extension)

Top-level shape:
  {
    _format: "suno-explorer-backup",
    _version: 1,
    clips: [ /* clip objects */ ],
    manualLinks: { childId -> parentId },
    playlists: { explorer: {}, suno: {} },
    preferences: {
      customNames, customTags, customNotes,
      definitiveVersions, releaseStatus, visibility,
      externalLinks, hideUnliked, customArt, disliked
    },
    downloads: [ /* download records */ ],
    settings: { /* extension settings */ }
  }

Most-used clip fields:
  id, title, baseTitle, audio_url, image_url, created_at, is_liked,
  major_model_version, project (workspace { id, name } or null),
  metadata.{ tags, prompt, gpt_description_prompt, type, duration,
            has_vocal, is_instrumental }
  Parent-relationship fields:
    upsample_clip_id, edited_clip_id, source_clip_id, concat_clip_id,
    cover_clip_id, continue_clip_id

Stability rules:
  - _version is semver-ish. Minor field additions don't bump it.
    Breaking removals/renames bump major and are pre-announced.
  - Treat all fields as optional defensively. Don't assume Suno-flagged
    booleans (has_vocal / is_instrumental) are accurate — many are wrong.
  - audio_url and image_url are Suno CDN URLs that expire. For long-lived
    references, prefer the clip id.

What I want to build:
  [DESCRIBE YOUR PROJECT HERE — e.g. "a CLI that exports a portable
   M3U playlist of my liked songs grouped by workspace", or "a stats
   dashboard with weekly upload counts", or "a script that finds
   orphaned clips with no inferred parent in lineage"]

Set up a project with:
  - A loader function that handles both .json and .compact.json files
  - Sensible defaults for missing fields
  - A README that explains how to use the tool
  - Tests for the loader and at least one feature

Use the dependencies and language you'd normally pick for this kind of
script — no exotic frameworks unless they're genuinely the right call.
Tip: If you're round-tripping data back into the extension (writing curation changes, importing new clips, syncing playlists), use the import action in Data Management. It accepts either format and merges with existing data. Don't write to the extension's IndexedDB directly — the import path validates and migrates as needed.

05More