# Beatport Scraper \[$0.40/1K💰] | Tracks | BPM & Key | DJ Charts (`ahmed_jasarevic/beatport-scraper`) Actor

Extract Beatport tracks, artists, releases and labels with BPM, musical key, Camelot notation, ISRC and prices. Search, charts and genre browse into clean, dataset-ready rows.

- **URL**: https://apify.com/ahmed_jasarevic/beatport-scraper.md
- **Developed by:** [Ahmed Jasarevic](https://apify.com/ahmed_jasarevic) (community)
- **Features:** Limited permissions
- **Stats:** 5 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 1,000 track results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Beatport Scraper

Extract DJ and electronic music catalog data from [Beatport](https://www.beatport.com) — tracks, artists, releases and labels — for music discovery, label and A\&R analytics, DJ tooling, and dance-music market research.

This Apify Actor reads Beatport's JSON catalog API directly. No browser, no HTML parsing, and no Cloudflare challenge. Track records include title, artists and remixers, label, genre, BPM, musical key (including Camelot notation), duration, price, ISRC, catalog number, release date, chart position, artwork, and the official 30–60 second preview URL. Search results can also be collected as artists, releases and labels, each in its own dataset. Queries run against Beatport's own search index, so result counts match [beatport.com/search](https://www.beatport.com/search) up to the Max results per type cap.

### Build A Dance-Music Dataset For DJ Tooling & A\&R

- **Harmonic mixing and playlist tools** — pull BPM, key and Camelot notation for every track so a DJ app can build harmonically compatible sets and filter by tempo.
- **Label and A\&R analytics** — browse labels, artists and releases, then measure catalog size, release cadence, genre mix and chart presence.
- **Music-licensing and sync research** — collect ISRCs, catalog numbers, release dates and label ownership for rights and clearance workflows.
- **Dance-music market tracking** — schedule searches and genre browse to monitor new releases, chart movements and pricing over time.
- **Electronic-music price watching** — track Beatport track prices by genre, label or artist for deal and catalog research.

### How It Works

![How the Beatport Scraper works: searches, charts and genre pages become track, artist, release and label rows with BPM, key and previews.](https://api.apify.com/v2/key-value-stores/oeuA0kLOyhbRM4fzt/records/how-it-works-beatport-scraper)

The Actor parses search queries, Beatport URLs and bare IDs into catalog targets, then fetches them from the same token-based JSON API the Beatport frontend uses. Results are hydrated into flat rows and written to a dataset per selected type.

Track rows include artists, remixers, label, genre, BPM, musical key, Camelot notation, ISRC, catalog number, price, release date, chart position, artwork and preview URL. Artist, release and label rows add their own catalog fields.

The Actor requests Beatport's public catalog API — the same JSON endpoints the beatport.com site and embed player use — and normalizes the responses into flat, analysis-ready rows.

1. Search queries, Beatport URLs and bare IDs are parsed into track, artist, release, label, chart and genre targets.
2. Each target is fetched from Beatport's token-based catalog API over plain HTTP.
3. Records for every selected result type are hydrated into full catalog rows (preview URL, slug, remixers, chart position and more).
4. Rows are written to a per-type dataset: Tracks (default), Artists, Releases and Labels.

No proxy is required — the JSON API is not aggressively rate-limited, and the Actor keeps concurrency low. With no input at all, the Actor browses the latest releases into the Tracks dataset.

### Input Parameters

| Field | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `startUrls` | array | No | — | Beatport track / release / artist / label / chart / genre / search URLs, or bare numeric IDs (`chart:906219` forces a type). Plain text counts as a search query. |
| `queries` | array | No | — | Free-text searches against Beatport's website search index (same results as beatport.com/search), e.g. `bicep`, `melodic house`. |
| `searchTypes` | array | No | `["tracks","artists","releases","labels"]` | Which result types to collect: `tracks`, `artists`, `releases`, `labels`. |
| `genre` | string | No | — | Genre browse into the Tracks dataset — slug, name or numeric ID; fuzzy-matched (`techno` → *Techno (Peak Time / Driving)*). |
| `sortBy` | string | No | `newest` | Genre-browse sort: `newest`, `oldest`, `bpm_asc`, `bpm_desc`. |
| `maxItems` | integer | No | `100` | Max results **per type** (free-plan users: 10 per type). |
| `maxPagesPerSource` | integer | No | `5` | API pages (≤150 results each) read per chart/artist/release/genre source; search queries are not paged. |
| `maxRequestsPerCrawl` | integer | No | `200` | Hard safety cap on API requests. |
| `proxy` | object | No | — | Optional Apify proxy picker (not needed — the JSON API works without it). |

### Output Fields

Track items are written to the default dataset. Simplified field list:

`trackId`, `title`, `mixName`, `artists`, `remixers`, `label`, `labelId`, `releaseName`, `releaseId`, `genre`, `subGenre`, `bpm`, `key`, `camelot`, `duration`, `durationMs`, `trackNumber`, `price`, `currency`, `isrc`, `catalogNumber`, `releaseDate`, `chartName`, `chartPosition`, `artworkUrl`, `previewUrl`, `sampleStartMs`, `sampleEndMs`, `isExplicit`, `isHype`, `isAvailableForStreaming`, `slug`, `url`, `source`.

Release items add `trackCount`, `bpmMin` / `bpmMax`, `upc`, `artists`, `remixers` and `labelId`. Artist items add `imageUrl`, `createdAt`, `updatedAt` and `website`. Label items add `latestPublishDate`, streaming/hype flags and image URLs.

### Example Input

Collect techno tracks and label results from one search, plus a chart:

```json
{
  "queries": ["peak time techno"],
  "searchTypes": ["tracks", "labels"],
  "startUrls": ["chart:906219"],
  "maxItems": 100
}
```

Browse the newest Drum & Bass releases sorted by BPM:

```json
{
  "genre": "drum-and-bass",
  "sortBy": "bpm_desc",
  "maxItems": 50
}
```

### Example Output

```json
{
  "trackId": 16871148,
  "title": "Tariro Nema Gitare",
  "mixName": "Original Mix",
  "artists": ["Josh Major"],
  "label": "Phakama Records",
  "genre": "Afro House",
  "bpm": 123,
  "key": "C Minor",
  "camelot": "5A",
  "duration": "6:31",
  "price": 1.49,
  "currency": "USD",
  "isrc": "US83Z2227774",
  "catalogNumber": "PHRS0001",
  "releaseDate": "2022-10-07",
  "artworkUrl": "https://geo-media.beatport.com/image_size/1400x1400/xxxx.jpg",
  "previewUrl": "https://geo-samples.beatport.com/track/xxxx.LOFI.mp3",
  "url": "https://www.beatport.com/track/tariro-nema-gitare/16871148",
  "source": "beatport"
}
```

Download any dataset as JSON, HTML, CSV or Excel.

### Automate Beatport Monitoring With Schedules & Webhooks

- **Schedule genre or label browse** (daily or weekly) to capture new releases and chart movements as they happen.
- **Send results to Zapier, Make, Google Sheets or your own webhook** to feed a dashboard, playlist pipeline or A\&R tracker.
- **Read the datasets via the Apify REST API** to hydrate a DJ app, licensing database or market-research tool.
- **Pay only for the results you keep** — see pricing below.

### Related Actors

- [MusicBrainz Scraper — Music Metadata Database](https://apify.com/lulzasaur/musicbrainz-scraper) — open music metadata to cross-reference artists, releases and recordings.
- [MusicBrainz Music Metadata API Scraper](https://apify.com/jungle_synthesizer/musicbrainz-music-metadata-api-scraper) — relationship graphs and cross-platform ID resolution (ISRC, Spotify, Discogs).
- [YouTube Audio Extractor](https://apify.com/ahmed_jasarevic/yt-audio-extractor) — pull audio from YouTube for preview and reference workflows.
- [SoundCloud Scraper](https://apify.com/ahmed_jasarevic/soundcloud-scraper) — collect independent electronic-music tracks, artists and engagement.
- [Slickdeals Scraper](https://apify.com/ahmed_jasarevic/slickdeals-scraper) — track deals and price drops across marketplaces.

### Frequently Asked Questions

#### Why use this Actor instead of the official Beatport API?

Beatport operates a documented REST API at `api.beatport.com/v4`, but new developer key registration has been effectively closed since the API v3 sunset — new credential requests typically stall or go unanswered. This Actor reads Beatport's publicly accessible catalog API the same way its own embed player does, so you get the same track, artist, release, label and chart data without waiting on API access.

#### What are alternatives to scraping Beatport?

Alternatives include the MusicBrainz open database (free, but not Beatport-specific and missing BPM/Camelot/price), general music-metadata APIs (Spotify, Discogs), or scraping Beatport's server-rendered `__NEXT_DATA__` blocks manually. This Actor combines Beatport's real catalog with structured BPM, key, ISRC and price fields in one run.

#### Can I get BPM and musical key for harmonic mixing?

Yes. Every track row includes `bpm`, `key` (e.g. `C Minor`) and `camelot` notation (e.g. `5A`), plus `duration`, so DJ software can build harmonically compatible sets.

#### How do I scrape a Beatport chart or genre?

Paste a chart or genre URL into `startUrls`, or use a bare ID such as `chart:906219`. You can also pass `genre` as a slug, name or numeric ID for genre browse.

#### Does the Actor include audio files?

No. It stores catalog metadata only — including the official 30–60 second preview URLs that Beatport publishes. Price and preview-URL availability are geo-dependent, and `geo-samples.beatport.com` previews may be restricted in some countries.

#### Why do my result counts differ from the website?

Search queries use Beatport's website search index and are hydrated with full catalog records, so counts match the website up to the Max results per type cap. Genre, label, artist and release endpoints page at ≤150 results each, controlled by `maxPagesPerSource`.

### For AI Agents & LLM Apps

Purpose: return normalized Beatport track, artist, release and label records for a given search, URL, chart or genre.

Minimal working input:

```json
{ "queries": ["adam beyer"], "searchTypes": ["tracks"], "maxItems": 25 }
```

Genre-browse variant:

```json
{ "genre": "techno", "sortBy": "newest", "maxItems": 25 }
```

Output fields (tracks): `trackId, title, mixName, artists, remixers, label, labelId, releaseName, releaseId, genre, subGenre, bpm, key, camelot, duration, price, currency, isrc, catalogNumber, releaseDate, chartName, chartPosition, artworkUrl, previewUrl, url, source`.

Behaviors an agent should know:

- Each selected result type writes to its **own dataset** (Tracks is the default); `maxItems` is a cap **per type**, not overall.
- `startUrls` accepts bare numeric IDs; prefix with a type (`chart:906219`, `label:1234`) to force interpretation. Plain text in `startUrls` is treated as a search query.
- With **no input at all**, the Actor browses the latest releases into the Tracks dataset.
- On the free Apify plan, `maxItems` is limited to 10 per type.
- Billing: pay-per-event — Track / Artist / Release / Label result each $0.0004 (Track is the primary event), plus a symbolic $0.00005 Actor-start event.

### Legal & Compliance Disclaimer

This is an independent Actor. It is not affiliated with, endorsed by, or sponsored by Beatport. It accesses only Beatport's publicly accessible catalog API — no login or account is required, and no paywalled or protected content is retrieved. It stores catalog metadata only; it does not download audio files or store personal data. Users are responsible for complying with Beatport's Terms of Service and applicable law when using the data. Price and preview-URL availability are geo-dependent.

### SEO Keywords

beatport scraper, beatport api, beatport catalog api, beatport track data, beatport bpm key data, beatport camelot key, electronic music data scraper, dj music metadata, beatport charts scraper, beatport label data, beatport artist data, beatport releases scraper, beatport genre browse, harmonic mixing bpm key, music isrc data, dance music market research, label a\&r analytics, music licensing data, beatport alternative, music metadata api

# Actor input Schema

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

Beatport track, release, artist, label, chart, genre or search URLs (e.g. https://www.beatport.com/chart/ade-2026/906215, https://www.beatport.com/search?q=techno, https://www.beatport.com/genre/techno/5/tracks). A search URL is scraped for every result type selected below. Bare numeric IDs are treated as track IDs; use a prefix such as "chart:906215" to force another type. Plain text is treated as a search query.

## `queries` (type: `array`):

Free-text searches against Beatport's website search index (the same results as beatport.com/search), e.g. "adam beyer", "peak time techno". Each query returns up to Max results per type for every result type selected below. Search is relevance-ranked, so Max pages per source does not apply to queries.

## `searchTypes` (type: `array`):

Which kinds of search results to collect for the search queries and search URLs. Each type is stored in its own dataset: Tracks in the default dataset, Artists / Releases / Labels in their own datasets. Explicit Beatport entity URLs (track, release, artist, label, chart, genre) are always scraped regardless of this setting.

## `genre` (type: `string`):

Browse the newest tracks of a genre into the tracks dataset. Accepts a genre/sub-genre slug or name (e.g. "techno", "melodic-house", "drum-bass") or a numeric genre ID. Leave empty to skip.

## `sortBy` (type: `string`):

Ordering used when browsing a genre.

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

Maximum number of results pushed to each dataset (tracks, artists, releases and labels are counted separately). Free users are capped at 10 results per type; paying users can request up to 5000.

## `maxPagesPerSource` (type: `integer`):

How many API pages (up to 150 results each) to read per chart/artist/release/genre source. Search queries are not paged; they are capped by Max results per type.

## `maxRequestsPerCrawl` (type: `integer`):

Hard safety cap on the number of API requests made in the run.

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

Select proxies to be used by your crawler.

## Actor input object example

```json
{
  "startUrls": [],
  "queries": [],
  "searchTypes": [
    "tracks",
    "artists",
    "releases",
    "labels"
  ],
  "genre": "",
  "sortBy": "newest",
  "maxItems": 100,
  "maxPagesPerSource": 5,
  "maxRequestsPerCrawl": 200,
  "proxy": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `tracks` (type: `string`):

One item per track with BPM, key + Camelot, ISRC, price, chart position, artwork and preview URL.

## `artists` (type: `string`):

One item per artist profile (search with type=artists).

## `releases` (type: `string`):

One item per release with artists, label, dates, track count, BPM range, price and UPC (search with type=releases).

## `labels` (type: `string`):

One item per record label (search with type=labels).

# 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": [],
    "queries": [],
    "searchTypes": [
        "tracks",
        "artists",
        "releases",
        "labels"
    ],
    "genre": "",
    "proxy": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed_jasarevic/beatport-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": [],
    "queries": [],
    "searchTypes": [
        "tracks",
        "artists",
        "releases",
        "labels",
    ],
    "genre": "",
    "proxy": { "useApifyProxy": False },
}

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

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).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": [],
  "queries": [],
  "searchTypes": [
    "tracks",
    "artists",
    "releases",
    "labels"
  ],
  "genre": "",
  "proxy": {
    "useApifyProxy": false
  }
}' |
apify call ahmed_jasarevic/beatport-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ahmed_jasarevic/beatport-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/EfoIE2xHYqmVrcIcP/builds/fOZTqTmiFHsvqDaF4/openapi.json
