A MusicBrainz-API-client for reading and submitting metadata
- Access metadata from MusicBrainz
- Submit metadata
- Smart and adjustable throttling, like MusicBrainz, it allows a bursts of requests
- Build in TypeScript definitions
MusicBrainz asks that you identifying your application by filling in the 'User-Agent' Header.
By passing appName
, appVersion
, appMail
musicbrainz-api takes care of that.
If you plan to use this module for submitting metadata, please ensure you comply with the MusicBrainz Code of conduct/Bots.
Import the module JavaScript example, how to import 'musicbrainz-api:
const MusicBrainzApi = require('musicbrainz-api').MusicBrainzApi;
const mbApi = new MusicBrainzApi({
appName: 'my-app',
appVersion: '0.1.0',
appContactInfo: '[email protected]'
});
In TypeScript it would look like this:
import {MusicBrainzApi} from 'musicbrainz-api';
const mbApi = new MusicBrainzApi({
appName: 'my-app',
appVersion: '0.1.0',
appContactInfo: '[email protected]' // Or URL to application home page
});
The following configuration settings can be passed
import {MusicBrainzApi} from '../src/musicbrainz-api';
const config = {
// MusicBrainz bot account username & password (optional)
botAccount: {
username: 'myUserName_bot',
password: 'myPassword'
},
// API base URL, default: 'https://musicbrainz.org' (optional)
baseUrl: 'https://musicbrainz.org',
appName: 'my-app',
appVersion: '0.1.0',
// Optional, default: no proxy server
proxy: {
host: 'localhost',
port: 8888
},
// Your e-mail address, required for submitting ISRCs
appMail: string
}
const mbApi = new MusicbrainzApi(config);
MusicBrainz API documentation: XML Web Service/Version 2 Lookups
Arguments:
- entity:
'artist'
|'label'
|'recording'
|'release'
|'release-group'
|'work'
|'area'
|'url'
- MBID (MusicBrainz identifier)
const artist = await mbApi.lookupEntity('artist', 'ab2528d9-719f-4261-8098-21849222a0f2');
const area = await mbApi.lookupArea('ab2528d9-719f-4261-8098-21849222a0f2');
Lookup an artist
and include their releases
, release-groups
and aliases
const artist = await mbApi.lookupArtist('ab2528d9-719f-4261-8098-21849222a0f2');
Lookup an instrument
const instrument = await mbApi.lookupInstrument('b3eac5f9-7859-4416-ac39-7154e2e8d348');
Lookup a label
const label = await mbApi.lookupLabel('25dda9f9-f069-4898-82f0-59330a106c7f');
const place = await mbApi.lookupPlace('e6cfb74d-d69b-44c3-b890-1b3f509816e4');
The second argument can be used to pass subqueries, which will return more (nested) information:
const artist = await mbApi.lookupArtist('ab2528d9-719f-4261-8098-21849222a0f2', ['releases', 'recordings', 'url-rels']);
The second argument can be used to pass subqueries:
const recording = await mbApi.lookupRecording('16afa384-174e-435e-bfa3-5591accda31c', ['artists', 'url-rels']);
const release = await mbApi.lookupRelease('976e0677-a480-4a5e-a177-6a86c1900bbf', ['artists', 'url-rels']);
const releaseGroup = await mbApi.lookupReleaseGroup('19099ea5-3600-4154-b482-2ec68815883e');
const work = await mbApi.lookupWork('b2aa02f4-6c95-43be-a426-aedb9f9a3805');
const url = await mbApi.lookupUrl('c69556a6-7ded-4c54-809c-afb45a1abe7d');
const area = await browseAreas(query);
Query argument | Query value |
---|---|
query.collection |
Collection MBID |
const artist = await browseArtist(query);
Query argument | Query value |
---|---|
query.area |
Area MBID |
query.collection |
Collection MBID |
query.recording |
Recording MBID |
query.release |
Release MBID |
query.release-group |
Release-group MBID |
query.work |
Work MBID |
const artist = await browseCollection(query);
Query argument | Query value |
---|---|
query.area |
Area MBID |
query.artist |
Artist MBID |
query.editor |
Editor MBID |
query.event |
Event MBID |
query.label |
Label MBID |
query.place |
Place MBID |
query.recording |
Recording MBID |
query.release |
Release MBID |
query.release-group |
Release-group MBID |
query.work |
Work MBID |
const events = await browseEvents(query);
Query argument | Query value |
---|---|
query.area |
Area MBID |
query.artist |
Artist MBID |
query.collection |
Collection MBID |
query.place |
Place MBID |
const instruments = await browseEvents(query);
Query argument | Query value |
---|---|
query.collection |
Collection MBID |
const labels = await browseLabels(query);
Query argument | Query value |
---|---|
query.area |
Area MBID |
query.collection |
Collection MBID |
query.release |
Release MBID |
const places = await browsePlaces(query);
Query argument | Query value |
---|---|
query.area |
Area MBID |
query.collection |
Collection MBID |
const recordings = await browseRecordings(query);
Query argument | Query value |
---|---|
query.artist |
Area MBID |
query.collection |
Collection MBID |
query.release |
Release MBID |
query.work |
Work MBID |
const places = await browseReleases(query);
Query argument | Query value |
---|---|
query.area |
Area MBID |
query.artist |
Artist MBID |
query.editor |
Editor MBID |
query.event |
Event MBID |
query.label |
Label MBID |
query.place |
Place MBID |
query.recording |
Recording MBID |
query.release |
Release MBID |
query.release-group |
Release-group MBID |
query.work |
Work MBID |
const places = await browseReleaseGroups(query);
Query argument | Query value |
---|---|
query.artist |
Artist MBID |
query.collection |
Collection MBID |
query.release |
Release MBID |
const places = await browseSeries();
Query argument | Query value |
---|---|
query.area |
Area MBID |
query.artist |
Artist MBID |
query.editor |
Editor MBID |
query.event |
Event MBID |
query.label |
Label MBID |
query.place |
Place MBID |
query.recording |
Recording MBID |
query.release |
Release MBID |
query.release-group |
Release-group MBID |
query.work |
Work MBID |
const places = await browseWorks();
Query argument | Query value |
---|---|
query.artist |
Artist MBID |
query.xollection |
Collection MBID |
const urls = await browseUrls();
Query argument | Query value |
---|---|
query.artist |
Artist MBID |
query.xollection |
Collection MBID |
Implements XML Web Service/Version 2/Search.
There are different search fields depending on the entity.
Searches can be performed using the generic search function: query(entity: mb.EntityType, query: string | IFormData, offset?: number, limit?: number)
Arguments:
- Entity type, which can be one of:
artist
: search fieldslabel
: search fieldsrecording
: search fieldsrelease
: search fieldsrelease-group
: search fieldswork
: search fieldsarea
: search fieldsurl
: search fields
query {query: string, offset: number, limit: number}
query.query
: supports the full Lucene Search syntax; you can find a detailed guide at Lucene Search Syntax. For example, you can set conditions while searching for a name with the AND operator.query.offset
: optional, return search results starting at a given offset. Used for paging through more than one page of results.limit.query
: optional, an integer value defining how many entries should be returned. Only values between 1 and 100 (both inclusive) are allowed. If not given, this defaults to 25.
For example, to find any recordings of 'We Will Rock You' by Queen:
const query = 'query="We Will Rock You" AND arid:0383dadf-2a4e-4d10-a46a-e9e041da8eb3';
const result = await mbApi.query<mb.IReleaseGroupList>('release-group', {query});
mbApi.search('area', 'Île-de-France');
Search a release with the barcode 602537479870:
mbApi.search('release', {query: {barcode: 602537479870}});
Same as previous example, but automatically serialize parameters to search query
mbApi.search('release', 'barcode: 602537479870');
The following entity specific search functions are available:
searchArtist(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IArtistList>
searchReleaseGroup(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IReleaseGroupList>`
Search artist:
const result = await mbApi.searchArtist({query: 'Stromae'});
Search release-group:
const result = await mbApi.searchReleaseGroup({query: 'Racine carrée'});
Search a combination of a release-group and an artist.
const result = await mbApi.searchReleaseGroup({artist: 'Racine carrée', releasegroup: 'Stromae'});
Submitting data via XML POST may be done using personal MusicBrainz credentials.
Using the XML ISRC submission API.
const mbid_Formidable = '16afa384-174e-435e-bfa3-5591accda31c';
const isrc_Formidable = 'BET671300161';
const xmlMetadata = new XmlMetadata();
const xmlRecording = xmlMetadata.pushRecording(mbid_Formidable);
xmlRecording.isrcList.pushIsrc(isrc_Formidable);
await mbApi.post('recording', xmlMetadata);
For all of the following function you need to use a dedicated bot account.
Use with caution, and only on a test server, it may clear existing metadata as side effect.const mbid_Formidable = '16afa384-174e-435e-bfa3-5591accda31c';
const isrc_Formidable = 'BET671300161';
const recording = await mbApi.lookupRecording(mbid_Formidable);
// Authentication the http-session against MusicBrainz (as defined in config.baseUrl)
const succeed = await mbApi.login();
assert.isTrue(succeed, 'Login successful');
// To submit the ISRC, the `recording.id` and `recording.title` are required
await mbApi.addIsrc(recording, isrc_Formidable);
const recording = await mbApi.lookupRecording('16afa384-174e-435e-bfa3-5591accda31c');
const succeed = await mbApi.login();
assert.isTrue(succeed, 'Login successful');
await mbApi.addUrlToRecording(recording, {
linkTypeId: LinkType.stream_for_free,
text: 'https://open.spotify.com/track/2AMysGXOe0zzZJMtH3Nizb'
});
Actually a Spotify-track-ID can be submitted easier:
const recording = await mbApi.lookupRecording('16afa384-174e-435e-bfa3-5591accda31c');
const succeed = await mbApi.login();
assert.isTrue(succeed, 'Login successful');
await mbApi.addSpotifyIdToRecording(recording, '2AMysGXOe0zzZJMtH3Nizb');
The JavaScript in runtime is compliant with ECMAScript 2017 (ES8). Requires Node.js® version 6 or higher.