# SoundCloud Scraper · Tracks + Artists + Emails · $1.50/1k (`memo23/soundcloud-scraper`) Actor

Scrape SoundCloud tracks, artists, playlists, albums, and search results in one actor — with management/booking emails parsed directly from artist bios. Auto-classifies any SoundCloud URL. Uses the public v2 JSON API (no browser, no client\_id setup). 30+ fields per row, JSON or CSV

- **URL**: https://apify.com/memo23/soundcloud-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Lead generation, Social media, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## SoundCloud Scraper — Tracks, Artists, Playlists, Search & Bio Emails

Auto-classify any SoundCloud URL — tracks, artist profiles, playlists/albums, or search queries — and get a clean structured dataset with **30+ fields per row** plus management/booking emails parsed directly from artist bios. Uses the public v2 JSON API (no browser, no client_id setup). Pure HTTP.

### How it works

<p align="center">
  <img src="https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-soundcloud.png" alt="How it works" width="100%" />
</p>

---

### Why use this scraper

- **All SoundCloud URL kinds in one input** — paste a track, an artist profile, a playlist, and a search query in the same array. Each is auto-classified and routed to the right v2 API endpoint. No separate actors per URL shape.
- **Bio emails included** — SoundCloud artists routinely put management/booking emails in their `description` field (e.g. Flume's bio begins with `Management: flume@threesixzero.com`). The actor parses these directly from the API response — no separate website fetch needed, ~30-50% hit rate on verified artists.
- **30+ fields per artist** — username, fullName, followers, followings, track count, playlist count, city, country, verified flag, pro subscription, creation date, avatar URL, bio, and more.
- **20+ fields per track** — title, plays, likes, reposts, comments, genre, tags, duration, license, label, release date, monetization model, artwork URL, waveform URL.
- **15+ fields per playlist/album** — title, track count, total duration, set type (album / EP / compilation), full track list with permalinks, genre, tags, release date, label name.
- **No browser, no client_id setup** — the actor extracts a fresh `client_id` from SoundCloud's JS bundle automatically (24h cache, auto-refresh on 401/403). No manual setup.
- **CSV-friendly flatten** — nested API objects auto-expand to underscore-separated top-level fields, perfect for spreadsheet workflows.

---

### Overview

SoundCloud has 175+ million tracks and 40+ million artists. Whether you're building a label scouting tool, a music-industry sales pipeline, a trend tracker, or a producer-collab finder, you eventually need this data in CSV.

The actor uses SoundCloud's public v2 JSON API (`api-v2.soundcloud.com`) — the same API the web app uses. Five URL shapes are auto-classified by URL pattern, so you don't tell the actor "what kind of URL this is"; you just paste URLs.

---

### Supported inputs

| Input | Row(s) emitted |
|---|---|
| **Track** — `/{artist}/{track-slug}` | 1 track row with title, plays, likes, reposts, genre, tags, duration, license, monetization, artwork. |
| **Artist profile** — `/{artist}` | 1 artist row with username, full name, followers, followings, track count, country, city, verified flag, pro subscription, bio — plus emails parsed from bio. |
| **Playlist or album** — `/{artist}/sets/{slug}` | 1 playlist row with title, set type (`album` / `ep` / `single` / `compilation` / `''` for plain playlist), track count, full track list (id + title + permalink for each), release date, label. |
| **Search** — `/search?q=...` | Fans out to up to N rows across `tracks` + `users` (filtered search supported: `/search/sounds`, `/search/people`, `/search/sets`, `/search/albums`). Cursor-paginated. |
| **Discover** — `/discover` | Fans out SoundCloud's curated mixed-selections panels (~40-60 playlist rows depending on `maxItems`). `/discover/sets/genre:{slug}` returns featured tracks for that genre. |

Mix any of these in the same `startUrls[]` array — the actor auto-classifies each one. JSON + CSV output.

> Pure HTTP. No browser, no client_id manual setup, no third-party services.

---

### Use cases

- **Label A&R** — find emerging electronic artists by `genre=techno` + `followers_count > 10000` + active in the last 6 months.
- **Music-industry sales pipeline** — collect management/booking emails for booking agents and labels by scraping artists in your target genre.
- **Track release monitor** — re-scrape your competitor labels' artists daily to catch new track uploads.
- **Producer/remix sourcing** — search by tag to find remixers; cold-pitch them via bio emails.
- **Genre trend tracker** — search by tag/keyword + sort by `playback_count` to find what's blowing up.
- **Playlist curation analysis** — pull a curator's full set list to study how they sequence tracks.
- **Verified-artist market research** — filter `verified=true` to study only the SoundCloud-verified accounts in your category.

---

### How it works (under the hood)

Five stages, all pure HTTP via the v2 JSON API, ~150ms per resolve call:

1. **Classify URL** — every input URL is matched against a deterministic regex set. Five URL shapes, one classifier function. Reserved paths (`/upload`, `/discover`, `/search`, etc.) are filtered out so they don't get misclassified as artists.
2. **Extract client_id** — SoundCloud's v2 API requires a `client_id` query param. On first call, the actor fetches one JS bundle from `a-v2.sndcdn.com`, scans for the pattern `client_id:"…"`, caches the result for 24h. Auto-refresh on 401/403.
3. **Call v2 API** — `resolve` endpoint for individual entities; `search/{tracks|users|albums|playlists}` for search queries. impit's Chrome TLS fingerprint + Referer header pass the API's anti-bot cleanly.
4. **Parse bio emails** — for artist rows, the actor runs an email regex over the `description` field (mailto + plain-text patterns, junk-filtered for CRM relays and template addresses). Surfaces as `harvestedEmails[]` field.
5. **Push flat row to dataset** — one row per track, artist, or playlist. Optionally flattened (CSV-friendly) or kept nested (JSON-rich).

End-to-end live smoke test: **12 rows from 5 mixed URLs** (2 artists + 1 playlist + 9 search results), 1 email harvested (`flume@threesixzero.com` from Flume's bio), 0 hard failures, completed in ~3 seconds.

---

### Input configuration

Field | Type | Required | Notes
--- | --- | --- | ---
`startUrls` | `string[]` | yes | Any mix of track / artist / playlist / search URLs. Auto-classified.
`harvestArtistEmails` | `boolean` | no | Default `true`. Parses emails from each artist's bio. Disable for slightly cleaner raw output.
`paginateSearch` | `boolean` | no | Default `true`. Follow cursor pagination on search URLs until `maxItems` is reached. Disable for first-page-only.
`flatten` | `boolean` | no | Default `true`. Flatten nested API objects to underscore-separated top-level keys for CSV-friendly output.
`includeRaw` | `boolean` | no | Default `false`. Attach the full v2 API response as a `raw` field on every row.
`hydratePlaylistTracks` | `boolean` | no | Default `true`. SoundCloud's playlist endpoint returns the first few tracks fully populated and the rest as id-only stubs. When enabled, the actor issues one extra `/tracks?ids=…` call per playlist to fill in titles and permalinks for every track. Disable to save one API call per playlist (titles for stub tracks will be `null`).
`maxItems` | `integer` | no | Hard cap on rows emitted (combined tracks + artists + playlists). Default `1000`. Free-tier users capped at `100`.
`maxConcurrency` | `integer` | no | API calls in parallel. Default `8`. SC's API is forgiving — 6-10 is the sweet spot.
`proxy` | `object` | no | Default: Apify Proxy. Provide your own residential pool only if you hit rate-limits — the API doesn't require one in testing.

#### Example input

```json
{
  "startUrls": [
    "https://soundcloud.com/skrillex",
    "https://soundcloud.com/flume",
    "https://soundcloud.com/skrillex/sets/recess",
    "https://soundcloud.com/search?q=techno",
    "https://soundcloud.com/search/people?q=label%20manager"
  ],
  "harvestArtistEmails": true,
  "paginateSearch": true,
  "maxItems": 500
}
````

***

### Output overview

Three row shapes, distinguished by the `rowType` field: `track`, `artist`, `playlist`.

#### `rowType: "artist"` — for `/{artist}` URLs

```jsonc
{
  "rowType":         "artist",
  "sourceUrl":       "https://soundcloud.com/flume",
  "userId":          2976616,
  "username":        "Flume",
  "fullName":        "",
  "permalinkUrl":    "https://soundcloud.com/flume",
  "avatarUrl":       "https://i1.sndcdn.com/avatars-...-large.jpg",
  "description":     "Management: flume@threesixzero.com\n...",
  "city":            "Sydney",
  "countryCode":     "AU",
  "followersCount":  2226886,
  "followingsCount": 203,
  "trackCount":      231,
  "playlistCount":   46,
  "likesCount":      1289,
  "repostsCount":    78,
  "verified":        true,
  "isPro":           true,
  "harvestedEmails": ["flume@threesixzero.com"],
  "scrapedAt":       "2026-05-26T..."
}
```

#### `rowType: "track"` — for `/{artist}/{track-slug}` URLs

```jsonc
{
  "rowType":           "track",
  "trackId":           74415567,
  "title":             "Scary Monsters and Nice Sprites",
  "permalinkUrl":      "https://soundcloud.com/skrillex/scary-monsters-and-nice-sprites",
  "durationMs":        249000,
  "genre":             "Dubstep",
  "tags":              ["dubstep", "electronic", "scary monsters"],
  "playbackCount":     127500000,
  "likesCount":        2500000,
  "repostsCount":      450000,
  "commentCount":      80000,
  "labelName":         "Big Beat Records",
  "license":           "all-rights-reserved",
  "artistId":          856062,
  "artistUsername":    "Skrillex",
  "artistUrl":         "https://soundcloud.com/skrillex"
  // 8 more fields...
}
```

#### `rowType: "playlist"` — for `/{artist}/sets/{slug}` URLs (also covers albums)

```jsonc
{
  "rowType":      "playlist",
  "playlistId":   91234567,
  "title":        "Recess",
  "setType":      "album",
  "isAlbum":      true,
  "trackCount":   11,
  "tracks": [
    { "id": 142535312, "title": "All Is Fair in Love and Brostep", "permalinkUrl": "..." },
    { "id": 142535313, "title": "Recess", "permalinkUrl": "..." }
    // ... 9 more
  ],
  "releaseDate":  "2014-03-18T00:00:00Z",
  "labelName":    "OWSLA",
  "artistUsername":"Skrillex"
  // 10 more fields...
}
```

***

### Key output fields

The most-used fields for filtering / scoring:

- **`harvestedEmails`** — `string[]` of plausible management/booking emails parsed from the artist bio. Empty when the bio has no email patterns.
- **`followersCount`** — primary popularity metric for artists. Skrillex = 6.6M. Use to filter "established artists" (e.g. `> 10000`).
- **`verified`** — boolean SoundCloud-verified flag. Useful for filtering only the "real" accounts.
- **`isPro`** — boolean derived from `creator_subscription.product.id`. Pro/Plus accounts are paying SC subscribers = serious artists.
- **`playbackCount`** + **`likesCount`** + **`commentCount`** — track engagement metrics. Combined → "trending track" score.
- **`genre`** + **`tags`** — for category filters. Tags include both single-word and quoted multi-word tags.
- **`countryCode`** — 2-letter ISO country. Filter for territorial campaigns.
- **`setType`** — distinguishes `album` / `ep` / `single` / `compilation` from regular playlists.

***

### FAQ

**Q: Do I need a SoundCloud account or API key?**
A: No. Everything in scope here is publicly accessible. The actor auto-extracts a fresh `client_id` from SoundCloud's public JS bundle on each run (cached 24h).

**Q: How am I billed for a run?**
A: Two pay-per-event line items combined:

- **Output record** — $0.0025 per row paid tier, $0.0015 free tier. One event per dataset row (track, artist, or playlist).
- **Additional data** — $0.0001 per event, charged at **2× the count of nested items** inside each row. That means each track listed inside a playlist row, each email harvested from an artist bio, and each tag on a track or playlist all bill at this rate.

So a Skrillex artist row with 0 emails costs just $0.0025. A Flume artist row with 1 email costs $0.0025 + (1 × 2 × $0.0001) = $0.0027. A 50-track playlist row with ~30 tags costs $0.0025 + ((50 + 30) × 2 × $0.0001) = $0.0185. The dense `/discover` panels (40-50 tracks per playlist, ~30 tags each) are where additional-data charges add up — you're getting a lot of dense data per primary row.

**Q: What's the realistic email-harvest rate?**
A: 30-50% of verified artists put a management/booking email in their bio. Smaller/hobbyist accounts rarely do. Rate depends heavily on your input list — top-tier artists (e.g. on a label scouting list) hit ~50%.

**Q: Why is `description` sometimes `null`?**
A: SoundCloud lets users leave their bio blank. Free / inactive accounts often have null descriptions. No bio → no email harvest possible.

**Q: Can I scrape a specific artist's full track catalog?**
A: V1 — pass the artist URL to get the artist row (track count + summary). The artist's individual track URLs would each need to be passed separately. A future version will support `/{artist}/tracks` as a fan-out URL.

**Q: How does Discover work, given SoundCloud removed the `/charts` endpoint?**
A: SC pulled the old `/charts?genre=…&kind=top` endpoint in 2026. The actor now uses what's still alive: `/mixed-selections` (4 curated panels of playlists — what you see on the `/discover` page itself) and `/featured_tracks/top/{genre}` (genre-targeted track lists). Pass `/discover` for the editorial panels or `/discover/sets/genre:{slug}` (e.g. `/discover/sets/genre:techno`) for genre-targeted tracks.

**Q: How does the actor handle SoundCloud's API rate limits?**
A: The actor uses impit's Chrome TLS fingerprint + a real Referer header — passes cleanly in testing. If you hit a 401/403, the actor auto-refreshes the `client_id` once and retries. Set `maxConcurrency` lower (4 or below) if you're seeing transient errors.

**Q: Does this work for SoundCloud Go+ exclusive tracks?**
A: The metadata for Go+ tracks is public (so you'll get title, artist, etc.), but the playable audio isn't accessible without a SoundCloud Go+ subscription. The actor scrapes metadata only.

**Q: Output format?**
A: JSON (Apify Dataset default) or CSV via the Apify Console "Export" tab. Default flatten makes CSV directly usable in Excel / Google Sheets.

***

### Support

Found a bug, hit an unexpected URL pattern, or want a new entity type supported? File feedback via the Apify Console "Issues" tab on this actor's page.

***

### Additional services

Open to building custom scrapers, data enrichment pipelines, or co-developing actors. Reach out via the Apify Console contact form on the [memo23 profile](https://apify.com/memo23).

***

### Explore more scrapers

These pair well with the SoundCloud scraper for music-industry workflows:

- **[Product Hunt Scraper](https://apify.com/memo23/producthunt-scraper)** — pull music-tech product launches and their founder emails. Pairs for "find the labels building tools".
- **[LinkedIn Profiles Scraper](https://apify.com/memo23/linkedin-profiles-cheerio)** — backfill artist profiles (where bio email is null).
- **[Y Combinator Scraper](https://apify.com/memo23/y-combinator-scraper)** — find music-tech startups going through YC.
- **[Trustpilot Scraper](https://apify.com/memo23/trustpilot-scraper-ppe)** — customer reviews for music-streaming services and labels.
- **[YouTube Comments Scraper](https://apify.com/memo23/youtube-comments-scraper)** — find SoundCloud artists' YouTube cross-platform presence + comment-driven outreach.

Full portfolio: [apify.com/memo23](https://apify.com/memo23).

***

### ⚠️ Disclaimer

This scraper accesses publicly available data on soundcloud.com via SoundCloud's public v2 JSON API. It does NOT bypass authentication, scrape private content, or access content not intended for public consumption.

Users are responsible for ensuring their use of this scraper complies with:

- **SoundCloud Terms of Service** — review at [soundcloud.com/terms-of-use](https://soundcloud.com/terms-of-use)
- **SoundCloud API Terms of Use** — review at [developers.soundcloud.com/docs](https://developers.soundcloud.com/docs)
- **Applicable data protection laws** including GDPR (Europe), CCPA (California), and equivalent regulations in your jurisdiction. Email harvesting falls under data-protection obligations — process responsibly, honor opt-outs, and consult legal counsel before using harvested emails for outbound marketing.
- **`robots.txt`** and rate-limiting guidance from SoundCloud
- **Local jurisdiction laws** regarding web scraping and data collection

The scraper is provided for legitimate purposes such as market research, label A\&R, music-industry sales pipelines, trend tracking, and personal use. Commercial use, redistribution, or use that violates SoundCloud's Terms of Service is the user's responsibility.

This actor is independently built and is not affiliated with, endorsed by, or sponsored by SoundCloud Limited.

By using this scraper, you acknowledge that you understand and accept these responsibilities.

***

### SEO Keywords

soundcloud scraper, soundcloud api, soundcloud data extraction, soundcloud tracks scraper, soundcloud artists scraper, soundcloud playlist scraper, soundcloud search scraper, soundcloud emails, soundcloud management contacts, soundcloud booking emails, soundcloud labels scraper, soundcloud a\&r tool, soundcloud verified artists, soundcloud genre tracker, soundcloud playback count, soundcloud followers scraper, soundcloud csv export, soundcloud trending tracks, soundcloud techno scraper, soundcloud electronic music data, soundcloud producer scraper, soundcloud remix sourcing, soundcloud market research, soundcloud apify, soundcloud automation, scrape soundcloud without api key, soundcloud without oauth, no-code soundcloud scraper, soundcloud v2 api scraper.

# Actor input Schema

## `startUrls` (type: `array`):

Full soundcloud.com URLs to scrape. Search URLs paginate automatically (cursor-based) until `Maximum items to scrape` is reached.

## `harvestArtistEmails` (type: `boolean`):

When enabled (default), each artist's bio (`description` field) is scanned for emails (mailto: links + plain-text patterns, junk filtered). SoundCloud artists routinely put management/booking emails in their bio (e.g. Flume's bio starts with `Management: flume@threesixzero.com`). Disable for slightly cleaner raw output.

## `paginateSearch` (type: `boolean`):

When enabled (default), search URLs follow cursor pagination (SC's `next_href` field) across multiple pages until `Maximum items to scrape` is reached. Disable to scrape only the first page of each search (~25 results).

## `flatten` (type: `boolean`):

When enabled (default), nested API objects (`user`, `media`, etc.) are flattened to underscore-separated top-level keys (e.g. `user_id`, `user_country_code`). Arrays-of-objects become JSON-stringified `*_json` fields. Disable to keep the raw nested JSON shape.

## `includeRaw` (type: `boolean`):

When enabled, the full v2 API response is attached as a `raw` field on every row — useful for accessing fields the actor doesn't surface explicitly. Off by default to keep rows small.

## `hydratePlaylistTracks` (type: `boolean`):

SoundCloud's playlist endpoint returns the first few tracks fully populated and the rest as id-only stubs (titles come back as `null` in `tracks_json`). When enabled (default), the actor issues one extra `/tracks?ids=…` call per playlist to backfill titles, permalinks, and full track metadata. Disable to keep playlist rows to a single API call — titles for stub tracks will remain `null`.

## `maxItems` (type: `integer`):

Hard cap on the number of rows emitted (tracks + artists + playlists combined). A single artist URL emits 1 row. A search URL fans out to ~25 rows per page × however many pages are available.

## `maxConcurrency` (type: `integer`):

Maximum number of API calls processed in parallel. SoundCloud's API is forgiving; 6-10 is the sweet spot.

## `minConcurrency` (type: `integer`):

Minimum number of API calls processed in parallel.

## `maxRequestRetries` (type: `integer`):

Number of retries before a failed API call is given up. 401/403 responses trigger an automatic client\_id refresh + single retry; this counter covers other failures.

## `proxy` (type: `object`):

Defaults to Apify Proxy. SoundCloud's v2 API doesn't require a proxy in our testing — impit's Chrome TLS fingerprint + the right Referer header is enough. Provide your own residential pool here only if you encounter rate-limits.

## Actor input object example

```json
{
  "startUrls": [
    "https://soundcloud.com/skrillex",
    "https://soundcloud.com/flume",
    "https://soundcloud.com/skrillex/scary-monsters-and-nice-sprites",
    "https://soundcloud.com/skrillex/sets/recess",
    "https://soundcloud.com/search?q=techno"
  ],
  "harvestArtistEmails": true,
  "paginateSearch": true,
  "flatten": true,
  "includeRaw": false,
  "hydratePlaylistTracks": true,
  "maxItems": 1000,
  "maxConcurrency": 8,
  "minConcurrency": 1,
  "maxRequestRetries": 5,
  "proxy": {
    "useApifyProxy": true
  }
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        "https://soundcloud.com/skrillex",
        "https://soundcloud.com/flume",
        "https://soundcloud.com/skrillex/scary-monsters-and-nice-sprites",
        "https://soundcloud.com/skrillex/sets/recess",
        "https://soundcloud.com/search?q=techno"
    ],
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/soundcloud-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "startUrls": [
        "https://soundcloud.com/skrillex",
        "https://soundcloud.com/flume",
        "https://soundcloud.com/skrillex/scary-monsters-and-nice-sprites",
        "https://soundcloud.com/skrillex/sets/recess",
        "https://soundcloud.com/search?q=techno",
    ],
    "proxy": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/soundcloud-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    "https://soundcloud.com/skrillex",
    "https://soundcloud.com/flume",
    "https://soundcloud.com/skrillex/scary-monsters-and-nice-sprites",
    "https://soundcloud.com/skrillex/sets/recess",
    "https://soundcloud.com/search?q=techno"
  ],
  "proxy": {
    "useApifyProxy": true
  }
}' |
apify call memo23/soundcloud-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=memo23/soundcloud-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "SoundCloud Scraper · Tracks + Artists + Emails · $1.50/1k",
        "description": "Scrape SoundCloud tracks, artists, playlists, albums, and search results in one actor — with management/booking emails parsed directly from artist bios. Auto-classifies any SoundCloud URL. Uses the public v2 JSON API (no browser, no client_id setup). 30+ fields per row, JSON or CSV",
        "version": "0.0",
        "x-build-id": "aDFgBgOi0Q3UQAS6s"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/memo23~soundcloud-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-memo23-soundcloud-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/memo23~soundcloud-scraper/runs": {
            "post": {
                "operationId": "runs-sync-memo23-soundcloud-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/memo23~soundcloud-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-memo23-soundcloud-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "startUrls": {
                        "title": "SoundCloud URLs",
                        "type": "array",
                        "description": "Full soundcloud.com URLs to scrape. Search URLs paginate automatically (cursor-based) until `Maximum items to scrape` is reached.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "harvestArtistEmails": {
                        "title": "Harvest contact emails from each artist's bio",
                        "type": "boolean",
                        "description": "When enabled (default), each artist's bio (`description` field) is scanned for emails (mailto: links + plain-text patterns, junk filtered). SoundCloud artists routinely put management/booking emails in their bio (e.g. Flume's bio starts with `Management: flume@threesixzero.com`). Disable for slightly cleaner raw output.",
                        "default": true
                    },
                    "paginateSearch": {
                        "title": "Paginate through search/discover results",
                        "type": "boolean",
                        "description": "When enabled (default), search URLs follow cursor pagination (SC's `next_href` field) across multiple pages until `Maximum items to scrape` is reached. Disable to scrape only the first page of each search (~25 results).",
                        "default": true
                    },
                    "flatten": {
                        "title": "Flatten nested fields for CSV-friendly output",
                        "type": "boolean",
                        "description": "When enabled (default), nested API objects (`user`, `media`, etc.) are flattened to underscore-separated top-level keys (e.g. `user_id`, `user_country_code`). Arrays-of-objects become JSON-stringified `*_json` fields. Disable to keep the raw nested JSON shape.",
                        "default": true
                    },
                    "includeRaw": {
                        "title": "Include full v2 API response on every row",
                        "type": "boolean",
                        "description": "When enabled, the full v2 API response is attached as a `raw` field on every row — useful for accessing fields the actor doesn't surface explicitly. Off by default to keep rows small.",
                        "default": false
                    },
                    "hydratePlaylistTracks": {
                        "title": "Hydrate playlist tracklist with full titles + metadata",
                        "type": "boolean",
                        "description": "SoundCloud's playlist endpoint returns the first few tracks fully populated and the rest as id-only stubs (titles come back as `null` in `tracks_json`). When enabled (default), the actor issues one extra `/tracks?ids=…` call per playlist to backfill titles, permalinks, and full track metadata. Disable to keep playlist rows to a single API call — titles for stub tracks will remain `null`.",
                        "default": true
                    },
                    "maxItems": {
                        "title": "Maximum items to scrape",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Hard cap on the number of rows emitted (tracks + artists + playlists combined). A single artist URL emits 1 row. A search URL fans out to ~25 rows per page × however many pages are available.",
                        "default": 1000
                    },
                    "maxConcurrency": {
                        "title": "Max concurrency",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Maximum number of API calls processed in parallel. SoundCloud's API is forgiving; 6-10 is the sweet spot.",
                        "default": 8
                    },
                    "minConcurrency": {
                        "title": "Min concurrency",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Minimum number of API calls processed in parallel.",
                        "default": 1
                    },
                    "maxRequestRetries": {
                        "title": "Max request retries",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Number of retries before a failed API call is given up. 401/403 responses trigger an automatic client_id refresh + single retry; this counter covers other failures.",
                        "default": 5
                    },
                    "proxy": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Defaults to Apify Proxy. SoundCloud's v2 API doesn't require a proxy in our testing — impit's Chrome TLS fingerprint + the right Referer header is enough. Provide your own residential pool here only if you encounter rate-limits."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
