AssetService:SearchAudioAsyncRead the docs →Find Similar
GEThttps://api.audioscape.ai/developer/v1/similarEndpoint
Given a track's asset ID — or a list of them, such as a playlist — find other tracks that sound similar. Great for building "more like this" features, or for continuing a playlist with tracks that fit the set as a whole.
Headers
| Name | Type | Description |
|---|---|---|
| x-api-key | required | Your API key |
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| asset_id | string required unless asset_ids | The Roblox asset ID of the track to find similar music for. Use this or asset_ids, not both. |
| asset_ids | string optional | Comma-separated list of up to 100 asset IDs (e.g. asset_ids=123,456,789) — the tracks of a playlist, say. Results match the acoustic profile of the whole set rather than any one track, and none of the seeds are returned. Seeds that can't be resolved (unknown, not yet analyzed, or not public) are skipped and listed in meta.seeds_ignored; if none resolve, the response is a 404. Order doesn't matter. |
| limit | number optional | Maximum results to return (default: 20, max: 100) |
| offset | number optional | Pagination offset (default: 0) |
| filters | object optional | JSON-encode the object and pass as a single querystring value (e.g. filters={"genres":["electronic"]}). Narrow your results:genres—Array of canonical genre values (e.g. "Electronic") or URL-safe slugs (e.g. "electronic"). Legacy Roblox music_genre slugs are also accepted and resolve to the canonical taxonomy.duration—Object with min and max in seconds |
| max_score | number optional | Drops results whose score is at or above this threshold (between 0 and 1). Useful for filtering out near-duplicates of the seed track. Omit to return all results. |
| dedupe | boolean optional | Shortcut for filtering near-duplicates without picking a number — equivalent to a sensible default max_score. If both are set, max_score wins. |
Response
Returns tracks that are acoustically similar to the given track.
Each track also carries additive optional MIR (music information retrieval) fields. They may be null when a track hasn't been analyzed, so always null-check. Note: loudness_lufs can be non-finite (Inf/NaN) — filter those out before ranking or averaging; danceability is long-tailed, so rank by percentile rather than an absolute cutoff; and genres_detailed scores are small — use their relative rank.
{
"tracks": [
{
"asset_id": "string",
"name": "string",
"artist": "string",
"album": "string",
"duration": number,
"genre": "string", // canonical, e.g. "Hip Hop / Rap"
"genre_slug": "string", // URL-safe, e.g. "hip-hop-rap" — pass to /v1/browse?type=genre&name=
"bpm": number,
"score": number,
// --- MIR fields (all optional, may be null) ---
"loudness_lufs": number, // integrated EBU R128 loudness; filter out Inf/NaN before ranking/averaging
"true_peak_dbtp": number, // true peak in dBTP; > 0 means over / clipping
"mood": { // each ~0..1 except arousal (−1..1); use arousal for relative energy
"arousal": number,
"happy": number,
"sad": number,
"aggressive": number,
"relaxed": number,
"party": number,
"danceable": number
},
"key": "string", // e.g. "C", "Eb"
"scale": "string", // "major" | "minor"
"key_confidence": number, // 0..1
"voice": "string", // "voice" | "instrumental"
"voice_confidence": number,// 0..1
"electronic": "string", // character label
"acoustic": "string", // character label
"timbre": "string", // character label
"danceability": number, // long-tailed — rank by percentile, not an absolute threshold
"genres_detailed": [ // top-5 Discogs predictions; use relative rank (scores are small)
{ "label": "string", "parent": "string", "score": number } // parent may be absent
]
}
],
"meta": {
"total": number,
"limit": number,
"offset": number,
// --- asset_ids requests only ---
"seeds_used": number, // seeds that resolved and were blended
"seeds_ignored": ["string"] // seeds skipped: unknown, not yet analyzed, or not public
}
}Example Request
Radio mode: when one track finishes, queue another that sounds like it so the vibe carries. Assumes a client from the Quickstart.
-- Radio mode: when the current track ends, queue one that sounds like it
-- Note: bgmSound.Looped must be false, otherwise Ended never fires
local nowPlayingId = "123456789"
bgmSound.Ended:Connect(function()
local result, err = AudioScape:similar({
asset_id = nowPlayingId,
limit = 1,
})
if not result or #result.tracks == 0 then
warn(err or "no similar tracks")
return
end
nowPlayingId = result.tracks[1].asset_id
bgmSound.SoundId = "rbxassetid://" .. nowPlayingId
bgmSound:Play()
end)Playlist continuation: pass a whole playlist (or any list of tracks, Sounds, or asset IDs) and get tracks that fit the set as a whole. Requires SDK 0.22.0 or later, or pass asset_ids directly over HTTP.
-- Playlist continuation: a creator's playlist is the seed, the API returns
-- tracks that sound like the whole set. Page with offset for the next batch.
local seed, err = AudioScape:getPlaylist({ playlist_id = "station-electronic-1712..." })
if not seed then warn(err) return end
local result, err2 = AudioScape:similar(seed.tracks, { limit = 20 })
if not result then warn(err2) return end
print(("blended %d seeds, skipped %d"):format(result.meta.seeds_used, #result.meta.seeds_ignored))
for _, track in result.tracks do
print(track.name, track.artist, track.score)
endError Responses
Missing or invalid asset ID, both asset_id and asset_ids given, or more than 100 asset_ids.
{
"error": "asset_id is required and must be a numeric string"
}Invalid or missing API key.
{
"error": "Invalid API key"
}The given asset ID is not in our catalog — or, for asset_ids, none of the given IDs resolved (asset_ids not found).
{
"error": "asset_id not found"
}You've exceeded your rate limit. See your current tier on the API Keys page.
{
"message": "Too Many Requests"
}Something went wrong on our end. Try again or contact support if the issue persists.