Udio Scraper - Prompts, Lyrics, Tags, Audio
Pricing
from $1.00 / 1,000 track results
Udio Scraper - Prompts, Lyrics, Tags, Audio
Collect public Udio tracks with the complete generation prompt, full lyrics, style tags, like and play counts, duration, artwork and a direct audio link. Search the catalogue by keyword and ordering, read a list of track addresses, or pull a public playlist in its original order.
Pricing
from $1.00 / 1,000 track results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Udio Scraper: Prompts, Lyrics, Tags & Audio
Udio Scraper turns Udio into a clean AI music data feed. Collect the exact generation prompt behind each public track, the complete lyrics with section markers intact, and the style tags the creator chose, together with the artwork, a direct audio link, like and play counts, duration, timestamps and the creator handle. Search the public catalogue by keyword and ordering, look up specific tracks by address, or pull every track in one or more public playlists in their own order, then export to JSON, CSV or Excel, or read the results straight through the API.
Why This Scraper?
- Three ways to find tracks. Search the catalogue by keyword and ordering, paste track addresses you already have, or read every track in one or more public playlists.
- Creative text kept verbatim. The full prompt, complete lyrics and style tags are carried through exactly as the creator wrote them, never trimmed or summarised.
- Nothing hand-picked is lost. Every field the platform sends comes through in
rawtoo, so a new upstream field reaches your dataset the day it appears. - True playlist order. Playlist mode reads the collection's own member list rather than the shorter preview the catalogue view shows, and restores the playlist's own order on every row.
- Built for schedules. Incremental mode returns only new, updated, reappeared and gone tracks on recurring runs, and unchanged tracks are not billed.
- Resume without paying twice. Finish one interrupted run by pointing at its run or dataset ID; tracks it already saved are skipped.
- A refused run fails loudly. If the site cannot be read, the run stops with a clear message instead of quietly returning an empty dataset.
Use Cases
- AI music researchers and dataset builders: collect prompt-to-track pairs at scale to study how wording shapes generated music.
- Playlist curators and fans: track a playlist's full membership, order and engagement over time.
- Music blogs and content teams: pull lyrics, tags and artwork to write about trending AI-generated tracks.
- Trend watchers: schedule recurring runs to see which tracks are gaining likes and plays.
- Archivists: keep a durable copy of a track's prompt and lyrics before it is edited or removed by its creator.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
| Field | Example |
|---|---|
trackId | "00000000-0000-4000-8000-000000000000" |
url | "https://www.udio.com/songs/00000000-0000-4000-8000-000000000000" |
title | "Midnight Coffee Loop" |
artist / creatorId | "Jane Doe" / "00000000-0000-4000-8000-000000000001" |
artistImageUrl | creator avatar image |
prompt | "lofi, jazzy chill cafe vibes, warm tape saturation" |
lyrics | "[Verse 1]\nRain on the window, cups going cold\n\n[Chorus]\nStay for one more song" |
tags / userTags | ["chill", "jazz", "downtempo", "instrumental"] / ["study"] |
description / attribution | free text, when the creator wrote one |
likeCount / playCount | 128 / 4210 |
durationSeconds | 131.2 |
createdAt / publishedAt | when the track was generated / made public |
audioUrl | direct link to the audio file |
videoUrl | direct link to the video, when one exists |
artworkUrl | cover artwork image |
styleId / styleSourceType / styleSourceTrackId | which style produced the track, when applicable |
parentTrackId | the track this one extends or remixes, when applicable |
generationId / generationStatus | the generation batch and its reported status |
isFinished / isPublishable | whether generation completed / may be shared |
collectionId / collectionName / collectionUrl / positionInCollection | playlist context; filled only in playlist mode (null in the other modes, where collectionUrl is left out) |
sourceMode | which mode produced the row |
scrapedAt | when the row was collected |
raw | every field exactly as the platform sent it |
How to Use
- Pick a mode: Search the catalogue (by keyword and ordering), Specific tracks (paste addresses or bare identifiers) or Playlist (paste playlist addresses or identifiers).
- Fill in the fields for that mode.
- Set Maximum tracks to control run size and cost, then click Start.
- Download the dataset as JSON, CSV or Excel, or read it through the API.
Search a keyword, newest first:
{"mode": "search","searchTerm": "lofi","sortBy": "newest","maxItems": 20}
Look up specific tracks:
{"mode": "songIds","trackIds": ["https://www.udio.com/songs/9765efef-43b4-4c0e-a3a0-ce288c99ccc7","baf84bf6-ff44-474b-aa4a-1e779776770d"]}
Read a whole public playlist, in its own order:
{"mode": "playlist","playlistIds": ["https://www.udio.com/playlists/6467edd4-f519-4418-b207-bd779b752627"],"maxItems": 0}
Browse the whole catalogue, most liked first:
{"mode": "search","sortBy": "mostLiked","maxItems": 50}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/udio-com-scraper").call(run_input={"mode": "search", "searchTerm": "lofi", "maxItems": 20})for track in client.dataset(run["defaultDatasetId"]).iterate_items():print(track["title"], track["prompt"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/udio-com-scraper').call({ mode: 'search', searchTerm: 'lofi', maxItems: 20 });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
The 200-track catalogue ceiling
A single catalogue query (one keyword and ordering, or the whole catalogue with no keyword) can reach at most 200 tracks, because that is as far as the site's own search view goes. Raising Maximum tracks past 200 does not reach more of that same query; run several searches with narrower keywords instead. Specific tracks and Playlist mode are not affected: they read an explicit, bounded set of identifiers rather than walking this ceiling.
Resume and recurring updates
These are two different things.
Resume finishes ONE interrupted run. Paste that run's ID (or its dataset ID) into resumeFromRunId; the tracks it already saved are skipped, so you don't pay twice. The new run still reads from the start of your selection, it simply does not re-publish what it recognises.
Incremental mode is for running the same selection again and again, daily say, to watch a playlist gain and lose tracks or a track's play count move. The actor remembers the previous run of that selection and, from the second run on, returns only what changed. Each row then carries changeType (NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED), changedFields, firstSeenAt and lastSeenAt. Memory is kept per selection (mode, keyword, ordering and lookup list); set stateKey to name a campaign or to deliberately share one. Resume and an existing Incremental mode memory cannot be combined in the same run; the run refuses with a clear message and asks you to run them separately.
EXPIRED rows are only produced when a run scanned the whole selection: not when Maximum tracks was reached and stopped it early, not when a catalogue search reached the 200-track ceiling, not when part of the selection (a private track, or a collection that is not public) could not be read, and not on a resumed run. When any of these applies, the run marks nothing as gone at all, and its log says which reason applied. Because of the ceiling, a catalogue search can only mark tracks as gone when it has fewer than 200 matches; to watch a larger set for removals, use Specific tracks or Playlist mode.
If a track appears in two of the playlists you list, it is published once, attributed to (and positioned within) the first playlist in your list that contains it; it is not silently dropped, just not duplicated.
Send results into your apps (MCP connectors)
Optionally pipe the collected tracks into apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the collection: the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each track, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text; nested objects collapse to their main value and long lists are trimmed, so the prompt and lyrics may be shortened there. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify > Settings > Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto the page where track pages should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | search, songIds, or playlist. |
searchTerm | string | (none) | Keyword matched against titles, prompts and tags (search mode). Empty browses the whole catalogue. |
sortBy | string | newest | newest, mostLiked, or mostPlayed (search mode). |
trackIds | array | sample | One track per line: a full track address or a bare identifier (specific tracks mode). |
playlistIds | array | sample | One playlist per line: a full playlist address or a bare identifier (playlist mode). |
maxItems | integer | 20 | Stop after this many tracks. 0 collects everything available for the selection. |
resumeFromRunId | string | (none) | Continue one interrupted run without returning tracks it already saved. |
incrementalMode | boolean | false | Return only new, updated, reappeared and gone tracks on recurring runs of the same selection. |
emitUnchanged | boolean | false | Also return (and bill) tracks unchanged since the last run, marked UNCHANGED. |
emitExpired | boolean | false | Also return (and bill) tracks gone since the last run, marked EXPIRED. Only when the whole selection was scanned. |
stateKey | string | (none) | Name or share an incremental-mode memory across runs. |
mcpConnectors | array | (none) | Optional: send a summary of each track to apps you authorized under Integrations. |
notionParentPageUrl | string | (none) | Notion connector only: page under which track pages are created. |
maxNotifyListings | integer | 50 | Cap on tracks written to each connector per run. Does not affect the dataset. |
proxyConfiguration | object | Apify Proxy | Connection settings for the run. |
Output Example
Sample shape: values are illustrative placeholders, not from a live record.
{"trackId": "00000000-0000-4000-8000-000000000000","url": "https://www.udio.com/songs/00000000-0000-4000-8000-000000000000","title": "Midnight Coffee Loop","artist": "Jane Doe","artistImageUrl": "https://example.com/avatar/sample.png","creatorId": "00000000-0000-4000-8000-000000000001","prompt": "lofi, jazzy chill cafe vibes, warm tape saturation","lyrics": "[Verse 1]\nRain on the window, cups going cold\n\n[Chorus]\nStay for one more song","tags": ["chill", "jazz", "downtempo", "instrumental"],"userTags": ["study"],"description": "","attribution": null,"likeCount": 128,"playCount": 4210,"durationSeconds": 131.2,"createdAt": "2026-01-05T09:12:44+00:00","publishedAt": "2026-01-05T09:15:02+00:00","audioUrl": "https://example.com/audio/sample.mp3","videoUrl": null,"artworkUrl": "https://example.com/art/sample.png","styleId": null,"styleSourceType": "style","styleSourceTrackId": null,"parentTrackId": null,"generationId": "00000000-0000-4000-8000-000000000002","generationStatus": "succeeded","isFinished": true,"isPublishable": true,"sourceMode": "search","collectionId": null,"collectionName": null,"positionInCollection": null,"scrapedAt": "2026-01-06T11:00:00+00:00","raw": {}}
Plan Requirement
The default connection works out of the box on every plan, and the actor rotates connections automatically when one is refused. Leave it as-is unless you have a reason to change it.
FAQ
How much does it cost?
You pay per track returned; unchanged tracks in Incremental mode are not billed unless you turn that on. The Pricing tab shows the current rates. Use Maximum tracks to cap the cost of any run.
Is it legal to scrape Udio?
This actor collects only publicly available Udio data. You are responsible for how you use it: follow Udio's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Generated audio, lyrics and artwork may carry rights distinct from the plain metadata, so treat creative fields with the same care you would any third-party creative work.
Can I get only new or changed tracks on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. From the second run on, each run returns only new, updated, reappeared and gone tracks for that selection, and unchanged ones are not billed unless you turn on Emit unchanged.
What is the difference between Resume and Incremental mode?
Resume finishes ONE interrupted run: paste its run or dataset ID into resumeFromRunId and already-saved tracks are skipped. Incremental mode compares each new run of the same selection against the previous one, on a schedule. They solve different problems and cannot be combined while an Incremental mode memory already exists for that selection; a run that tries fails with a message asking you to run them separately.
Why didn't a capped run mark any tracks as gone?
EXPIRED needs a complete look at the selection. A run stopped by Maximum tracks, a catalogue search that hit the 200-track ceiling, a private track or an unreadable playlist, and a resumed run all leave part of the selection unchecked, so none of them may declare anything gone that run; the log states which of these applied. For example, if 60 tracks in a 120-track playlist changed since the last run and Maximum tracks is 50, the run stops after returning 50 and emits no EXPIRED rows, even with Emit expired on. (In Incremental mode the cap counts only tracks actually returned, so a quiet day with fewer changes than the cap still counts as a full scan.) To get a real expiry sweep, periodically run the same selection with Maximum tracks set to 0 (or above the selection's size), alongside your smaller day-to-day capped runs. This works for Specific tracks, Playlist mode, and catalogue searches with fewer than 200 matches. A catalogue search with 200 or more matches always stops at the ceiling, so no setting of Maximum tracks lets it mark tracks as gone.
Why did my run fail instead of returning an empty dataset?
If the site refuses every request, or returns tracks this build cannot recognise at all, the run stops with a clear message so "nothing matched" is never confused with "nothing could be read". A keyword that genuinely matches nothing, or an incremental run where nothing changed, still succeeds with zero published rows. Before giving up, the actor automatically retries the whole request once more on a premium connection pool whenever the default pool is refused on every attempt, so a temporary refusal wave usually costs a few seconds, not the run. Runs that bring their own proxy connections or turn the proxy off keep exactly the connection they configured.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
๐ Want more AI data?
Pair this actor with these related scrapers from the same team:
| ๐ค Suno Scraper Collect public Suno music data: songs with lyrics, style tags, model version, play and... | ๐ฑ Universal Media Extractor Extract videos, audio, and metadata from 1000+ websites including YouTube, TikTok... |
| ๐ฑ Truth Social Scraper Scrape public Truth Social profiles, posts, media, metrics, author data, and complete... | ๐งฉ TIDAL Scraper Scrape TIDAL tracks, albums, artists, playlists and public mixes by search phrase or URL... |
| ๐ฑ Google Play Reviews Collect Google Play reviews and ratings for any app across country storefronts. Search by... | ๐งฉ KKday Scraper Scrape KKday travel activities by keyword, city or URL. Every row carries prices... |
๐ Browse all abotapi scrapers
๐ฌ Support & custom scrapers
- ๐ Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- ๐ ๏ธ Need another site, extra fields or a private build? Email contact@abotapi.com or message Telegram @abotapi.
- โญ Enjoying it? A quick review on the actor page helps other users find it.