Suno Scraper - Songs, Playlists, Creators & Lyrics avatar

Suno Scraper - Songs, Playlists, Creators & Lyrics

Pricing

from $1.30 / 1,000 result records

Go to Apify Store
Suno Scraper - Songs, Playlists, Creators & Lyrics

Suno Scraper - Songs, Playlists, Creators & Lyrics

Collect public Suno music data: songs with lyrics, style tags, model version, play and like counts, audio, video and cover art links, plus playlist and creator records. Choose the curated Explore sections, specific playlists, or a creator's full public catalogue.

Pricing

from $1.30 / 1,000 result records

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

7 days ago

Last modified

Categories

Share

Suno Scraper: Songs, Playlists, Creators and Lyrics

Suno Scraper turns Suno into a clean music-catalogue dataset. Every song record carries the title, the full lyric sheet, the style prompt, the model version, play and like counts, the creator identity, and direct links to the audio, video and cover art. Point it at the curated Explore sections, at specific playlist links, or at creator handles, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.

Why This Scraper?

  • Three ways in. Read the curated Explore sections, paste playlist links or ids, or paste creator handles. No need to build URLs by hand.
  • Four record kinds in one dataset. Songs, playlists, creator profiles and contests share one dataset, told apart by a recordType column, so a single run can map a whole corner of the catalogue.
  • 40+ fields per song. The complete lyric sheet, the style prompt, duration, model version, remix and stem availability, and the audio, video and cover art links.
  • Full depth, not just the first screen. A large playlist or a prolific creator's whole public catalogue comes back complete, up to your record cap, rather than stopping at the first batch.
  • One shared cap. Max records is the only limit that stops a run, and it is split fairly across the sources you asked for, so the last playlist in your list is never starved by the first.
  • Lyrics are optional. Turn them off for a dataset that is a fraction of the size when you only need titles, styles and counts.
  • Built for schedules. Turn on recurring updates and later runs return only what is new, updated or reappeared, each labelled in a changeType column, so a daily job does not re-deliver the same catalogue.

Use Cases

  • Music data researchers and ML teams: build lyric, style-tag and prompt datasets for text and audio generation research.
  • Trend watchers: monitor the trending and editorial sections to see which styles, prompts and model versions are rising.
  • Playlist archivists: export a whole playlist, songs and stats included, to catalogue or back it up.
  • Creator analytics: track a creator's public catalogue, play and upvote counts, and follower growth over time.
  • Contest followers: watch community contest windows, submission playlists and the base songs they remix.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
recordType"song" (also "playlist", "profile", "contest")
id"00000000-0000-0000-0000-000000000001"
url"suno.com/song/00000000-0000-0000-0000-000000000001"
title"Sample Song Title"
createdAt"2026-01-01T00:00:00.000Z"
creatorHandle"samplecreator"
creatorDisplayName"Sample Creator"
creatorProfileUrl"suno.com/@samplecreator"
creatorIsVerifiedfalse
playCount1200
upvoteCount85
commentCount4
durationSeconds180.5
styleTags"synth pop, driving bass, 120 BPM, male vocals"
displayTags["synth pop", "dance-pop"]
lyrics"[Verse 1]\nSample lyric line here\n\n[Chorus]\n..."
modelVersion"v6"
isInstrumentalfalse
isRemixfalse
hasStemsfalse
imageUrl"https://cdn0.example.com/image_00000000.jpeg"
audioUrl"https://cdn0.example.com/clip/00000000.m4a"
videoUrl"https://cdn0.example.com/00000000.mp4"
sourceType"playlist" (also "section", "profile")
scrapedAt"2026-01-01T00:00:00Z"

Playlist records add description, songCount, totalDurationSeconds, upvoteCount, playCount and the owning creator. Creator profile records add followersCount, followingCount, totalPlays, totalUpvotes, profileDescription and a playlists array you can feed straight back into playlists mode. Contest records add startTime, endTime, judgingStart, judgingEnd, winnersAnnouncedDate and the submissions playlist link.

How to Use

  1. Pick a mode: Explore sections (the curated discovery page), Playlists (paste links or ids), or Creator profiles (paste handles or links).
  2. Fill in the fields for that mode. In Creator profiles, you can also switch on reading every playlist linked on the profile.
  3. Set Max records to control run size and cost, then click Start.
  4. Download the dataset as JSON, CSV or Excel, or read it through the API.

Collect from the curated Explore sections (the default):

{
"mode": "explore",
"maxItems": 50
}

Pin one named section instead of every section:

{
"mode": "explore",
"exploreFeeds": ["trending"],
"maxItems": 100
}

Collect from two playlists, sharing the cap between them:

{
"mode": "playlists",
"playlistUrls": [
"suno.com/playlist/0d597d0c-cdb2-4f9c-b4da-57931929f0d0",
"990fd5fe-70d2-449b-8a4d-3cb0a7d3e805"
],
"maxItems": 500
}

Pull a creator's whole public catalogue plus every playlist on their profile, without lyrics:

{
"mode": "profiles",
"profileUrls": ["@samplecreator"],
"profileSortBy": "play_count",
"followProfilePlaylists": true,
"includeLyrics": false,
"maxItems": 0
}

Playlist links and bare ids are both accepted, and so are @handle, a bare handle and a full creator page link.

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/suno-music-scraper").call(run_input={"mode": "explore", "maxItems": 50})
for record in client.dataset(run["defaultDatasetId"]).iterate_items():
print(record["recordType"], record.get("title"))

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/suno-music-scraper').call({ mode: 'explore', maxItems: 50 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

How the record cap is shared across sources

Max records is one budget for the whole run. When a run reads several sources (several pinned sections, several playlists, several profiles), the remaining budget is split evenly across the sources still to come, and an exhausted source hands its unused share to the ones after it. A source's own container record (a playlist or profile header) never eats the whole share of a source, so even a source whose share is one record still returns a song rather than only its own header. Raise Max records, or set it to 0, to collect everything a source holds.

Resume and recurring updates

Two separate features, and they are not interchangeable.

  • Continue a previous run (resumeFromRunId): paste an earlier run id or dataset id. Every record that run already returned is skipped, so an interrupted large collection can finish without paying for the same rows twice.
  • Recurring updates (incrementalMode): for a scheduled job over the same scope. The first run returns everything as NEW. Every later run labels each record NEW, UPDATED (with changedFields), UNCHANGED (suppressed and not billed unless emitUnchanged is on), REAPPEARED, or EXPIRED (only after a run that scanned the whole scope, and only with emitExpired). stateKey names or shares the stored state; leave it empty and the memory is keyed on the run setup automatically. Play, like and comment counts move constantly on an active catalogue, so a record whose only difference is a counter still counts as UPDATED.

Once recurring updates already holds a baseline for a setup, a run that also sets resumeFromRunId is refused with a clear message: use one or the other, or pick a different stateKey.

A record is only ever reported EXPIRED after a run that reached the natural end of every source it read. A run stopped by Max records, a run that continued a previous one, a run where a source failed or was cut short, and a run that collected nothing all skip gone-record detection entirely (with emitExpired on, the run log says why), because absence proves nothing when the scan was incomplete.

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify, Settings, API & Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where items 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

ParameterTypeDefaultDescription
modestringexploreexplore, playlists, or profiles. Each mode reads only its own fields below.
exploreFeedsarrayemptyExplore mode only. Section ids to read, such as trending, editorial-best-of or contests. Empty covers every curated section the discovery page currently offers.
playlistUrlsarraysamplePlaylists mode only. Playlist page links or bare playlist ids.
profileUrlsarraysampleProfiles mode only. Creator page links, @handle or a bare handle.
profileSortBystringupvote_countOrder of a creator's songs and playlists: upvote_count (most liked), created_at (newest first), or play_count (most played).
followProfilePlaylistsbooleanfalseProfiles mode only. After a creator's own songs, also include every public playlist listed on that profile.
includeLyricsbooleantrueInclude the full lyric sheet on every song record. Turn off for a much smaller dataset.
maxItemsinteger20Stop after this many records across the whole run (0 = no limit). Songs, playlist headers, creator profiles and contests all count.
maxPagesinteger200Runaway guard: an upper bound (1 to 200) on how much is read for any single playlist, profile or section. Leave at the maximum so Max records is the only real limit.
resumeFromRunIdstring(none)Continue one interrupted run: its run id or dataset id. Records it already returned are skipped.
incrementalModebooleanfalseRecurring updates. Later runs of the same setup return only what changed, labelled in changeType.
stateKeystring(none)Optional name for a recurring-updates campaign, so its memory stays stable or is deliberately shared.
emitUnchangedbooleanfalseAlso return (and bill) records that did not change, labelled UNCHANGED.
emitExpiredbooleanfalseAlso return (and bill) records that are no longer found, labelled EXPIRED. Only produced by a complete run.
mcpConnectorsarray(none)Optional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstring(none)Notion connector only: page under which item pages are created.
maxNotifyListingsinteger50Cap (1 to 1000) on items written to each connector per run. Does not affect the dataset.
proxyConfigurationobjectApify ProxyConnection used for every request.

Output Example

Sample shape: values are illustrative placeholders, not from a live record.

{
"recordType": "song",
"id": "00000000-0000-0000-0000-000000000001",
"url": "suno.com/song/00000000-0000-0000-0000-000000000001",
"title": "Sample Song Title",
"createdAt": "2026-01-01T00:00:00.000Z",
"status": "complete",
"creatorHandle": "samplecreator",
"creatorDisplayName": "Sample Creator",
"creatorProfileUrl": "suno.com/@samplecreator",
"creatorIsVerified": false,
"playCount": 1200,
"upvoteCount": 85,
"commentCount": 4,
"durationSeconds": 180.5,
"styleTags": "synth pop, driving bass, 120 BPM, male vocals",
"displayTags": ["synth pop", "dance-pop"],
"lyrics": "[Verse 1]\nSample lyric line here\n\n[Chorus]\nSample chorus line here",
"modelName": "sample-model",
"modelVersion": "v6",
"isInstrumental": false,
"isRemix": false,
"canRemix": true,
"hasStems": false,
"isExplicit": false,
"imageUrl": "https://cdn0.example.com/image_00000000.jpeg",
"videoUrl": "https://cdn0.example.com/00000000.mp4",
"audioUrl": "https://cdn0.example.com/clip/00000000.m4a",
"sourceType": "playlist",
"sourceTitle": "Sample Playlist",
"sourceUrl": "suno.com/playlist/00000000-0000-0000-0000-000000000003",
"scrapedAt": "2026-01-01T00:00:00Z"
}

Plan Requirement

The actor runs on any Apify account. Suno's public catalogue answers ordinary connections, so the default proxy setting shipped in the input works without changes. Adjust it under Connection only if you have a specific reason to route requests differently.

FAQ

How much does it cost?

You pay per record returned. The Pricing tab shows the current rates. Use Max records to cap the cost of any run.

This actor collects only publicly available music catalogue data. You are responsible for how you use it: follow Suno's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Lyrics, audio and cover art may carry their own copyright even though the catalogue listing is public.

Can I get only new or changed songs on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Recurring updates (incrementalMode). Each run then returns only new, updated and reappeared records, and unchanged ones are not billed unless you ask for them.

Why did my run return fewer records than a playlist or profile actually holds?

Max records caps the whole run, not each source, and the remaining budget is split across every source you asked for. Raise Max records, or set it to 0, to collect a source in full.

Why did my run fail instead of returning an empty dataset?

If every requested source refused to answer, the run stops with a clear message so "this playlist is empty" is never confused with "nothing could be read". Run it again in a few minutes. If the requested sources answered but hold no public records, the run also stops, with a different message saying so, so check the playlist links, handles or section ids. The one exception is a recurring-updates run where every record was unchanged: that is a normal, successful run with nothing new to return.

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 a summary of each record into Notion, Linear or Airtable.

🔗 Want more AI data?

Pair this actor with these related scrapers from the same team:

🤖 Udio Scraper
Collect public Udio tracks with the complete generation prompt, full lyrics, style tags...
🧩 Anghami Scraper
Scrape Anghami's public catalog by keyword or player URL. Rows carry their kind (song...
📱 TikTok Profile, Hashtag, Search, Video & Trending Scraper
Scrape TikTok without login. Extract profiles, bios, follower stats and videos; search by...
🧩 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...
📱 ViewStats Scraper
Scrape YouTube channel analytics from ViewStats. Look up channels by handle, URL, or...

👉 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 abotapi@proton.me or message Telegram @abotapi.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.