# MusicBrainz Scraper (`dami_studio/musicbrainz-scraper`) Actor

MusicBrainz scraper for artists, releases, recordings, release groups and labels. Every row carries the MBID, a permanent ID you can join on later, plus the name or title, type, dates, country, credits and a link. Keywords or Lucene syntax. No login. $0.20 per 1,000 records.

- **URL**: https://apify.com/dami_studio/musicbrainz-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Developer tools, AI, Other
- **Features:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.19 / 1,000 items

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

**Search MusicBrainz for artists, releases, recordings, albums and labels and get flat rows back**,
each with its MBID, the permanent ID you can join on later, plus the name, type, dates, country and
a direct link. No API key, no login.

One thing to know before you plan a big pull: MusicBrainz serves at most 500 records for one search,
however many it matched, so a run returns 500 at most. For more, split the search into narrower ones
and run each. It also asks callers to go slowly, so this reads 100 records a page with about a second
between pages.

| | |
|---|---|
| **Input** | An entity type and a search term |
| **Output** | One row per record: MBID, link, relevance score, and the name or title, type, dates, country and credits for that kind of record |
| **Ceiling** | 500 records per search, all MusicBrainz serves for one search |
| **Account needed** | None, and no API key |
| **Price** | $0.20 per 1,000 records on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 25,000 |

### 🔍 What MusicBrainz Scraper does

It runs one search against MusicBrainz and pages through the answers until it has the number you
asked for, the catalogue runs out, or it reaches 500, the most MusicBrainz serves for one search. Rows are deduplicated on MBID as it goes, so a paginated pull
never hands you the same record twice.

`entity` decides what kind of thing you get back, and the five kinds are genuinely different:

| `entity` | What it is |
|---|---|
| `artist` | A band, a performer or a composer. |
| `release` | One specific edition of an album or single, the actual product. |
| `recording` | A single track. |
| `release-group` | An album as a concept, tying its editions together. |
| `label` | A record label. |

`query` takes plain keywords like `ok computer`, and it also takes MusicBrainz's own Lucene syntax,
so `artist:radiohead` and `country:GB` both work.

### 📋 What data you get from each MusicBrainz record

Five fields are on every row, whatever you searched for:

| What you get | Field |
|---|---|
| The MusicBrainz ID | `mbid` |
| The musicbrainz.org page for that record | `url` |
| Which kind of record the row is | `entity` |
| MusicBrainz's own relevance score for your search, 0 to 100 | `score` |
| The short note that tells same-named records apart | `disambiguation` |

The rest depend on the entity:

| Entity | Fields you also get |
|---|---|
| `artist` | `name`, `sortName`, `type`, `country`, `lifeSpan`, `beginDate`, `endDate`, `ended`, `tags` |
| `release` | `title`, `status`, `artistCredit`, `date`, `country`, `trackCount`, `primaryType` |
| `recording` | `title`, `artistCredit`, `date`, `firstReleaseDate`, `length` in milliseconds, `lengthFormatted` as `m:ss` |
| `release-group` | `title`, `type`, `primaryType`, `secondaryTypes`, `artistCredit`, `date`, `firstReleaseDate` |
| `label` | `name`, `type`, `country`, `lifeSpan`, `beginDate`, `endDate`, `labelCode` |

### ▶️ How to scrape MusicBrainz

1. Open [MusicBrainz Scraper](https://apify.com/dami_studio/musicbrainz-scraper) and click
   **Try for free**.
2. Pick an **Entity type**. Artist is the default.
3. Type your term into **Search query**.
4. Set **Max results**. Start around 10 to see the shape of the output, then click **Start**.
5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.

### 💰 How much does it cost to scrape MusicBrainz?

**$0.20 per 1,000 records** on the Free plan. Paid plans pay a little less: $0.198 on Starter, $0.196 on Scale and $0.194 on Business. On the free plan, the $5
Apify gives you each month covers about 25,000 records.

You pay per record delivered. Duplicate MBIDs across pages are dropped before anything is charged,
and diagnostic rows are not charged. Set a maximum cost on the run and it stops when it gets there.

### 📥 What you give it

```json
{
  "entity": "release-group",
  "query": "ok computer",
  "maxItems": 50
}
```

| Field | Default | What it is |
|---|---|---|
| `entity` | `artist` | `artist`, `release`, `recording`, `release-group` or `label`. |
| `query` | none, the form starts with `radiohead` | The text to search for. Keywords or Lucene syntax. An API call has to send its own. |
| `maxItems` | `100` | 1 to 10,000, counted after deduplication. One search still returns at most 500: that is all MusicBrainz serves for a single search. |
| `notionConnector` | none | Optional. Writes one Notion page per record when the run finishes. |
| `notionParentId` | none | Optional. The Notion data source to write into. Leave it empty and the pages land privately in your workspace. |
| `proxyConfiguration` | off | Optional network settings. A normal run does not need them. |

Send an empty `query` and the run returns a `BAD_INPUT` row instead of records.

### 📤 What you get back

A real `artist` row from a run on 2 October 2026, with the tag list cut short because it runs to
dozens:

```json
{
  "ok": true,
  "mbid": "a74b1b7f-71a5-4011-9441-d0b5e4122711",
  "entity": "artist",
  "url": "https://musicbrainz.org/artist/a74b1b7f-71a5-4011-9441-d0b5e4122711",
  "score": 100,
  "disambiguation": null,
  "name": "Radiohead",
  "sortName": "Radiohead",
  "type": "Group",
  "country": "GB",
  "artistCredit": null,
  "date": null,
  "lifeSpan": "1991 –",
  "beginDate": "1991",
  "endDate": null,
  "ended": null,
  "tags": ["alternative rock", "art rock", "rock", "electronic", "british", "..."]
}
```

| Field | How to read it |
|---|---|
| `mbid` | Stable and unique, and the reason most people run this. |
| `disambiguation` | The second match for `radiohead` in the same run was "On a Friday", with the note `pre‐Radiohead group, until 1991`. That note is how you tell records apart. |
| `artistCredit` | The credited string the way MusicBrainz writes it, so `A feat. B` stays `A feat. B`. |
| `tags` | Sorted by vote count, and user-made, so expect the odd strange one far down the list. |

A field MusicBrainz has no value for comes back `null` rather than missing.

### 🧾 Reading the output

Two kinds of row land in your dataset.

| Row | How to spot it | Billed |
|---|---|---|
| A record | `ok: true` and an `mbid` | yes |
| A diagnostic | `ok: false` and an `errorCode` | no |

| Code | What it means |
|---|---|
| `BAD_INPUT` | `query` was empty, `entity` was not one of the five, or MusicBrainz turned the search down as invalid (its own words are in `details`). |
| `NO_RESULTS` | The search ran and matched nothing. |
| `SEARCH_LIMIT` | The search matched more than the 500 records MusicBrainz serves for one search, and you asked for more. The records delivered are complete and charged; this row is free, and `reportedTotal` says how many the search matched. |
| `NETWORK` | MusicBrainz was unreachable or answered badly. Re-run it. |
| `TIME_LIMIT` | The run got close to its time limit and stopped on its own. The records delivered before that are complete and charged. Give the run more time, or ask for fewer records, to get the rest. |

A run that ends on one of these rows still finishes as succeeded, including when the time limit
stopped it before any record came back: the `TIME_LIMIT` row and an amber status message say so.

**A malformed Lucene query can come back as `NO_RESULTS` rather than an error.** If a search you
expected to match returns nothing, check the syntax before you conclude the record is not there.

### 💡 What people use it for

- Resolving a messy catalogue of artist or album names to MBIDs, so everything downstream has one
  key to join on.
- Filling in release dates, countries and label codes for a back catalogue.
- Pulling a genre slice with Lucene syntax, then sorting on `score` to see what actually matched.
- Checking whether a release exists in the open catalogue at all before adding it by hand.

### 🚧 What it does not do

- **Search only.** No lookup by MBID, no browsing an artist's releases, no track listings.
- **No more than 500 records from one search.** That cap is MusicBrainz's own. Several narrower
  searches get you more.
- **No audio, no cover art, no chart positions.**
- **Relevance ordering is MusicBrainz's.** `score` is its search score, not a popularity measure.
- **Large runs are slow on purpose.** The pacing is what MusicBrainz asks of callers, and this
  actor keeps to it.
- **If a page fails partway through a long run, the run ends with a diagnostic row** and the records
  already collected do not land. On big pulls, several smaller runs are safer than one huge one.
- **A malformed query reads as no results**, not as a syntax error.
- It is not an official MusicBrainz tool. Dami's Studio is independent and is not affiliated with or endorsed by MusicBrainz, or by any other company named on this page.

### 🧭 Which film, TV, music or game scraper do you need?

| If you want | Use |
|---|---|
| IMDb IDs for films, shows and people | [IMDb Search Scraper](https://apify.com/dami_studio/imdb-scraper) |
| Critic and audience scores for a film or show | [Rotten Tomatoes Scraper](https://apify.com/dami_studio/rotten-tomatoes-scraper) |
| TV shows, full episode lists and main cast | [TV Show Scraper](https://apify.com/dami_studio/tvmaze-scraper) |
| Artists, releases, recordings and labels, with their MBIDs | This one |
| Steam games, store details and player reviews | [Steam Scraper](https://apify.com/dami_studio/steam-scraper) |
| Goodreads ratings and rating counts for books | [Goodreads Books Scraper](https://apify.com/dami_studio/goodreads-books-scraper) |
| Wikidata Q-ids and claims for the same people and works | [Wikidata Scraper](https://apify.com/dami_studio/wikidata-scraper) |

### ❓ Questions people ask

#### Do I need a MusicBrainz account or key?

No. The search API is open.

#### What is an MBID for?

It is a permanent identifier for one record. Store it once and you can re-find or re-join that
artist, album or track later even if the name changes.

#### Can I look a record up by its MBID?

Not with this one. It searches by text.

#### Why did my run stop at 500 records?

MusicBrainz serves at most 500 records for one search, however many it matched. The run stops there,
delivers them, and adds a free `SEARCH_LIMIT` row with the number the search matched. To get the rest,
split it into narrower searches with Lucene syntax, `love AND tag:rock` for example, and run each one.

#### Can I call it from code or connect it to an AI assistant?

The [API tab](https://apify.com/dami_studio/musicbrainz-scraper/api/python) has code for Python, JavaScript and the
CLI. MCP clients like Claude and ChatGPT use
`https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/musicbrainz-scraper`; coding assistants can load [our
skill file](https://api.apify.com/v2/key-value-stores/BTBHU3DdiuoF4JOsK/records/apify-open-data-research-SKILL.md).
All three bill your Apify account at the same price.

#### Can I use MusicBrainz data commercially?

MusicBrainz core data is CC0 and the rest sits under its own
[data licences](https://musicbrainz.org/doc/About/Data_License). Read those and credit MusicBrainz
when you redistribute. Apify's write-up on
[the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) covers the wider
question, and we are not lawyers.

### 🆘 If something breaks

Open the **Issues** tab on the actor page. Send the entity, the exact query and the run ID. The
`errorCode` on the diagnostic row usually names the problem on its own.

# Actor input Schema

## `entity` (type: `string`):

Which kind of music record to search for. artist = bands/performers, release = a specific album/single edition, recording = an individual track, release-group = an album as a concept across editions, label = a record label.

## `query` (type: `string`):

The text to search for. Plain keywords work (e.g. "radiohead", "ok computer"), and MusicBrainz Lucene syntax is also supported (e.g. artist:radiohead, country:GB). Required.

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

Maximum number of records to return. One search returns at most 500, because that is all MusicBrainz serves for a single search; to get more, split the query into narrower searches and run each one. Records come 100 a page, about a second apart, as MusicBrainz asks.

## `notionConnector` (type: `string`):

Optional. Write each item as a page into your Notion when the run finishes. Authorize a Notion connector once in Settings → API & Integrations → MCP connectors, then pick it here. Leave empty to skip (default), results are always saved to the dataset regardless.

## `notionParentId` (type: `string`):

Optional. The Notion data source ID of the database to write into (only used if a Notion connector is set). Leave empty to create the pages privately in your workspace instead.

## `proxyConfiguration` (type: `object`):

Optional, and not needed for a normal run.

## Actor input object example

```json
{
  "entity": "artist",
  "query": "radiohead",
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Scraped rows are stored in the default dataset (one row per result). Blocked/empty/error runs return a single uncharged diagnostic row instead.

# 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 = {
    "query": "radiohead"
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/musicbrainz-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 = { "query": "radiohead" }

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/musicbrainz-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 '{
  "query": "radiohead"
}' |
apify call dami_studio/musicbrainz-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/musicbrainz-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/7tdFriZMdkoYy81ad/builds/eWq4zaSOw7OtE46hl/openapi.json
