{"id":13581022,"url":"https://github.com/patrickkfkan/bandcamp-fetch","last_synced_at":"2025-04-10T01:06:47.508Z","repository":{"id":39698973,"uuid":"331101629","full_name":"patrickkfkan/bandcamp-fetch","owner":"patrickkfkan","description":"Library for scraping Bandcamp content.","archived":false,"fork":false,"pushed_at":"2024-12-13T09:44:42.000Z","size":1020,"stargazers_count":48,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-03T00:06:33.808Z","etag":null,"topics":["api","bandcamp","scraper"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/patrickkfkan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"ko_fi":"patrickkfkan"}},"created_at":"2021-01-19T20:30:23.000Z","updated_at":"2025-02-07T09:45:25.000Z","dependencies_parsed_at":"2024-01-16T20:32:47.242Z","dependency_job_id":"5d1cc428-65a6-42b3-b442-2a574730fb57","html_url":"https://github.com/patrickkfkan/bandcamp-fetch","commit_stats":{"total_commits":91,"total_committers":1,"mean_commits":91.0,"dds":0.0,"last_synced_commit":"7a7241785cf19fe9aa8e8a281a505ccdb4c9bd30"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickkfkan%2Fbandcamp-fetch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickkfkan%2Fbandcamp-fetch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickkfkan%2Fbandcamp-fetch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickkfkan%2Fbandcamp-fetch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/patrickkfkan","download_url":"https://codeload.github.com/patrickkfkan/bandcamp-fetch/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247903406,"owners_count":21015649,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","bandcamp","scraper"],"created_at":"2024-08-01T15:01:57.335Z","updated_at":"2025-04-10T01:06:47.482Z","avatar_url":"https://github.com/patrickkfkan.png","language":"TypeScript","funding_links":["https://ko-fi.com/patrickkfkan","https://ko-fi.com/C0C5RGOOP'"],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003ca href='https://ko-fi.com/C0C5RGOOP' target='_blank'\u003e\u003cimg height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi2.png?v=3' border='0' alt='Buy Me a Coffee at ko-fi.com' /\u003e\u003c/a\u003e\n\n# bandcamp-fetch\n\nLibrary for scraping Bandcamp content.\n\nCoverage:\n\n- Bandcamp Discover\n- Album and track info\n- Artists, labels, label artists, discography\n- Articles (aka. Bandcamp Daily)\n- Shows\n- Tags, including releases and highlights by tag\n- Search\n- Fan collections, wishlists and following artists / genres\n\nPackaged as ESM + CJS hybrid module with typings.\n\n# Installation\n\n```\nnpm i bandcamp-fetch --save\n```\n\n# Usage\n\n```\nimport bcfetch from 'bandcamp-fetch';\n\nconst results = await bcfetch.discovery.discover(...);\n```\n\n### User Sessions\n\nWhen you sign into Bandcamp, a \"Cookie\" is created to identify the user session. You can pass the value of this cookie to the library and gain access to your private collection as well as high-quality MP3 streams of purchased media:\n\n```\nbcfetch.setCookie('xxxx');\n\nconst album = await bcfetch.album.getInfo({\n    albumUrl: '...'  // URL of purchased album\n});\n\n// Normal quality stream\nconst streamUrl = album.tracks[0].streamUrl;\n\n// High quality stream - only available when `cookie` is set\nconst streamUrlHQ = album.tracks[0].streamUrlHQ;\n```\n\nGuide: [How to obtain Cookie](https://github.com/patrickkfkan/bandcamp-fetch/wiki/How-to-obtain-Cookie)\n\n### `BandcampFetch`\n\nThe library exports a default [BandcampFetch](./docs/api/classes/BandcampFetch.md) instance mainly for backward compatibility with previous versions:\n\n```\n// Imports the default `BandcampFetch` instance\nimport bcfetch from 'bandcamp-fetch';\n```\n\nYou can also create separate instances. This is useful when you want to support multiple user sessions:\n\n```\nimport { BandcampFetch } from 'bandcamp-fetch';\n\nconst bcfetch1 = new BandcampFetch({\n    cookie: 'xxxx' // Cookie for user session 1\n});\n\nconst bcfetch2 = new BandcampFetch();\nbcfetch2.setCookie('yyyy'); // Cookie for user sesion 2\n```\n\n### \n\n# API\n\n## Discovery API\n\nTo access the Discovery API:\n\n```\nimport bcfetch from 'bandcamp-fetch';\n\nconst discovery = bcfetch.discovery;\n\nconst options = await discovery.getAvailableOptions();\nconst results = await discovery.discover(...);\n```\n**Methods:**\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003ediscover([params])\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/discovery/discover.mjs) ([output](examples/discovery/discover_output.txt))\n\n\u003cp\u003eFetches items through Bandcamp Discover.\u003c/p\u003e\n\n**Params**\n\n- `params`: ([DiscoverParams](docs/api/interfaces/DiscoverParams.md)) (*optional* and *all properties optional*)\n    - `genre`: (string)\n    - `subgenre`: (string) only valid when `genre` is set to something other than 'all'.\n    - `location`: (string)\n    - `sortBy`: (string)\n    - `category`: (number)\n    - `time`: (number)\n    - `customTags`: (Array\u0026lt;string\u0026gt;)\n    - `size`: number\n    - `albumImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md))\n    - `artistImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md))\n    - `merchImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md))\n\nTo see what values can be set in `params`, call `getAvailableOptions()`.\n\n**Returns**\n\nPromise resolving to [DiscoverResult](docs/api/interfaces/DiscoverResult.md).\n\n**Continuation**\n\nCheck the `continuation` property of the returned result to see if more results are available. To obtain the next set of results, pass the value of `continuation` to `discover()`:\n\n```\nconst results = await discovery.discover(...);\n\n// More results\nif (results.continuation) {\n  const moreResults = await discovery.discover(results.continuation);\n  ...\n}\n```\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetAvailableOptions()\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/discovery/getAvailableOptions.mjs) ([output](examples/discovery/getAvailableOptions_output.txt))\n\n\u003cp\u003eFetches Bandcamp Discover options that can be used to configure \u003ccode\u003eparams\u003c/code\u003e for passing into \u003ccode\u003ediscover()\u003c/code\u003e.\u003c/p\u003e\n\n**Returns**\n\nPromise resolving to [DiscoverOptions](docs/api/interfaces/DiscoverOptions.md).\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003esanitizeDiscoverParams([params])\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/discovery/sanitizeDiscoverParams.mjs) ([output](examples/discovery/sanitizeDiscoverParams_output.txt))\n\n\u003cp\u003eSanitizes \u003ccode\u003eparams\u003c/code\u003e by setting default values for omitted properties and removing irrelevant or inapplicable ones.\u003c/p\u003e\n\n\u003cp\u003e\nNote that you don't have to call this method on params passed into \u003ccode\u003ediscover()\u003c/code\u003e as they will be sanitized automatically.\n\u003c/p\u003e\n\n**Params**\n\n- `params`: ([DiscoverParams](docs/api/interfaces/DiscoverParams.md)) (*optional*) the discover params to sanitize.\n\n**Returns**\n\nPromise resolving to sanitized [DiscoverParams](docs/api/interfaces/DiscoverParams.md).\n\n---\n\u003c/details\u003e\n\n## Image API\n\nTo access the Image API:\n\n```\nimport bcfetch, { ImageFormatFilter } from 'bandcamp-fetch';\n\nconst image = bcfetch.image;\n\nconst formats = await image.getFormats(ImageFormatFilter.Album);\n```\n**Methods:**\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetFormats([filter])\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/image/getFormats.mjs) ([output](examples/image/getFormats_output.txt))\n\n\u003cp\u003eFetches the list of image formats used in Bandcamp.\u003c/p\u003e\n\n**Params**\n\n- `filter`: ([ImageFormatFilter](docs/api/enums/ImageFormatFilter.md)) (*optional*) if specified, narrows down the result to include only formats applicable to the specified value.\n\n**Returns**\n\nPromise resolving to Array\u003c[ImageFormat](docs/api/interfaces/ImageFormat.md)\u003e.\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetImageFormat(target, [fallbackId])\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n\u003cp\u003eFetches the image format that matches \u003ccode\u003etarget\u003c/code\u003e. If none is found, the result will be \u003ccode\u003enull\u003c/code\u003e.\u003c/p\u003e\n\n**Params**\n\n- `target`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md))\n    - If target is string or number, the method finds the image format with matching name or Id (as appropriate).\n    - If target satisfies the [ImageFormat](docs/api/interfaces/ImageFormat.md) interface constraint, then it is returned as is.\n- `fallbackId`: (number) (*optional*) if no match is found for `target`, try to obtain format with Id matching `fallbackId`.\n\n**Returns**\n\nPromise resolving to matching [ImageFormat](docs/api/interfaces/ImageFormat.md), or `null` if none matches `target` nor `fallbackId` (if specified).\n\n---\n\u003c/details\u003e\n\n\n## Band API\n\nA band can be an artist or label. To access the Band API:\n\n```\nimport bcfetch from 'bandcamp-fetch';\n\nconst band = bcfetch.band;\n\nconst info = await band.getInfo(...);\n```\n\n**Methods:**\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetInfo(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/band/getInfo.mjs) ([output](examples/band/getInfo_output.txt))\n\n\u003cp\u003eFetches information about an artist or label.\u003c/p\u003e\n\n**Params**\n\n- `params`: ([BandAPIGetInfoParams](docs/api/interfaces/BandAPIGetInfoParams.md))\n    - `bandUrl`: (string)\n    - `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n    - `labelId`: (number) (*optional*)\n\nThe method tries to assemble the most complete set of data by scraping the following pages (returning immediately at any point the data becomes complete):\n\n1. The page referred to by `bandUrl`\n2. The 'music' page of the artist or label (`bandUrl/music`)\n3. The first album or track in the artist's or label's discography\n\nSometimes, label information is missing for artists even when they do belong to a label. If you know the `labelId` of the label that the artist belongs to, you can specify it in `params`. This will ensure that `label` will not be `null` in the artist info. If you pass a label URL to this function, you can find the `labelId` in the result.\n\n**Returns**\n\nPromise resolving to [Artist](docs/api/interfaces/Artist.md) or [Label](docs/api/interfaces/Label.md).\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetLabelArtists(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/band/getLabelArtists.mjs) ([output](examples/band/getLabelArtists_output.txt))\n\n\u003cp\u003eFetches the list of artists belonging to a label.\u003c/p\u003e\n\n**Params**\n\n- `params`: ([BandAPIGetLabelArtistsParams](docs/api/interfaces/BandAPIGetLabelArtistsParams.md))\n    - `labelUrl`: (string)\n    - `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n\n**Returns**\n\nPromise resolving to Array\u003c[LabelArtist](docs/api/README.md#labelartist)\u003e.\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetDiscography(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/band/getDiscography.mjs) ([output](examples/band/getDiscography_output.txt))\n\n\u003cp\u003eFetches the list of albums and standalone tracks belonging to an artist or label.\u003c/p\u003e\n\n**Params**\n\n- `params`: ([BandAPIGetDiscographyParams](docs/api/interfaces/BandAPIGetDiscographyParams.md))\n    - `bandUrl`: (string)\n    - `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n\n**Returns**\n\nPromise resolving to Array\u003c[Album](docs/api/interfaces/Album.md) | [Track](docs/api/interfaces/Track.md)\u003e.\n\n---\n\u003c/details\u003e\n\n\n## Album API\n\nTo access the Album API:\n\n```\nimport bcfetch from 'bandcamp-fetch';\n\nconst album = bcfetch.album;\n\nconst info = await album.getInfo(...);\n```\n\n**Methods:**\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetInfo(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/album/getInfo.mjs) ([output](examples/album/getInfo_output.txt))\n\n\u003cp\u003eFetches info about an album.\u003c/p\u003e\n\n**Params**\n\n- `params`: ([AlbumAPIGetInfoParams](docs/api/interfaces/AlbumAPIGetInfoParams.md))\n    - `albumUrl`: (string)\n    - `albumImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n    - `artistImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n    - `includeRawData`: (boolean) (*optional)\n\n**Returns**\n\nPromise resolving to [Album](docs/api/interfaces/Album.md).\n\n\u003e If artist URL is not found in the scraped data, then `artist.url` will be set to the same value as `publisher.url`\n\n---\n\u003c/details\u003e\n\n## Track API\n\nTo access the Track API:\n\n```\nimport bcfetch from 'bandcamp-fetch';\n\nconst track = bcfetch.track;\n\nconst info = await track.getInfo(...);\n```\n\n**Methods:**\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetInfo(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/track/getInfo.mjs) ([output](examples/track/getInfo_output.txt))\n\n\u003cp\u003eFetches info about a track.\u003c/p\u003e\n\n**Params**\n\n- `params`: ([TrackAPIGetInfoParams](docs/api/interfaces/Tra))\n    - `trackUrl`: (string)\n    - `albumImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n    - `artistImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n    - `includeRawData`: (boolean) (*optional)\n\n**Returns**\n\nPromise resolving to [Track](docs/api/interfaces/Track.md).\n\n\u003e If artist URL is not found in the scraped data, then `artist.url` will be set to the same value as `publisher.url`\n\n---\n\u003c/details\u003e\n\n## Tag API\n\nTo access the Tag API:\n\n```\nimport bcfetch from 'bandcamp-fetch';\n\nconst tags = await bcfetch.tag.list();\n```\n\n**Methods:**\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003elist()\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/tag/list.mjs) ([output](examples/tag/list_output.txt))\n\n\u003cp\u003eFetches a list of tags.\u003c/p\u003e\n\n**Returns**\n\nPromise resolving to [TagList](docs/api/interfaces/TagList.md), which groups results into `tags`(for non-location tags) and `locations` (for location tags).\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetRelated(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/tag/getRelated.mjs) ([output](examples/tag/getRelated_output.txt))\n\n**Params**\n\n- `params`: ([TagAPIGetRelatedParams](docs/api/interfaces/TagAPIGetRelatedParams.md))\n    - `tags`: (Array\u0026lt;string\u0026gt;)\n    - `size`: (number) (*optional*)\n\n\u003cp\u003eFetches the related tags for each value in `tags`, as well as the combined result.\u003c/p\u003e\n\n**Returns**\n\nPromise resolving to [RelatedTags](docs/api/interfaces/RelatedTags.md), which has the following properties:\n- `single`: list of related tags for each tag queried\n- `combo`: the combined result of all the related tags\n\n---\n\u003c/details\u003e\n\n## Show API\n\nTo access the Show API:\n\n```\nimport bcfetch from 'bandcamp-fetch';\n\nconst show = bcfetch.show;\n\nconst list = await show.list(...);\n```\n\n**Methods:**\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003elist(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/show/list.mjs) ([output](examples/show/list_output.txt))\n\n\u003cp\u003eFetches the full list of Bandcamp shows.\u003c/p\u003e\n\nEach list entry contains basic info about a show. To obtain full details, pass its `url` to `getShow()`.\n\n**Params**\n\n- `params`: ([ShowAPIListParams](docs/api/interfaces/ShowAPIListParams.md)) (*optional*)\n    - `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n\n**Returns**\n\nPromise resolving to Array\u003c[Show](docs/api/interfaces/Show.md)\u003e.\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetShow(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/show/getShow.mjs) ([output](examples/show/getShow_output.txt))\n\n\u003cp\u003eFetches full details about the Bandcamp show referred to by \u003ccode\u003eparams.showUrl\u003c/code\u003e.\u003c/p\u003e\n\n**Params**\n\n- `params`: ([ShowAPIGetShowParams](docs/api/interfaces/ShowAPIGetShowParams.md))\n    - `showUrl`: (string)\n    - `albumImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n    - `artistImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n    - `showImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n\n**Returns**\n\nPromise resolving to [Show](docs/api/interfaces/Show.md).\n\n---\n\u003c/details\u003e\n\n## Article API\n\nTo access the Article API:\n\n```\nimport bcfetch from 'bandcamp-fetch';\n\nconst article = bcfetch.article;\n\nconst list = await article.list(...);\n```\n\n**Methods:**\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetCategories()\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/article/getCategories.mjs) ([output](examples/article/getCategories_output.txt))\n\n\u003cp\u003eFetches the list of Bandcamp Daily article categories. Categories are grouped into sections.\u003c/p\u003e\n\n**Returns**\n\nPromise resolving to Array\u003c[ArticleCategorySection](docs/api/interfaces/ArticleCategorySection.md)\u003e.\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003elist(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/article/list.mjs) ([output](examples/article/list_output.txt))\n\n\u003cp\u003eFetches the list of Bandcamp Daily articles under the category specified by \u003ccode\u003eparams.categoryUrl\u003c/code\u003e (or all categories if not specified).\u003c/p\u003e\n\n**Params**\n\n- `params`: ([ArticleAPIListParams](docs/api/interfaces/ArticleAPIListParams.md)) (*optional* and *all properties optional*)\n    - `categoryUrl`: (string)\n    - `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md))\n    - `page`: (number)\n\n**Returns**\n\nPromise resolving to [ArticleList](docs/api/interfaces/ArticleList.md).\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetArticle(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/article/getArticle.mjs) ([output](examples/article/getArticle_output.txt))\n\n\u003cp\u003eFetches the contents of the Bandcamp Daily article at \u003ccode\u003eparams.articleUrl\u003c/code\u003e.\u003c/p\u003e\n\n**Params**\n\n- `params`: ([ArticleAPIGetArticleParams](docs/api/interfaces/ArticleAPIGetArticleParams.md))\n    - `articleUrl`: (string)\n    - `albumImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n    - `artistImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n    - `includeRawData`: (boolean) (*optional*)\n\n**Returns**\n\nPromise resolving to [Article](docs/api/interfaces/Article.md).\n\n---\n\u003c/details\u003e\n\n## Fan API\n\nTo access the Fan API:\n\n```\nimport bcfetch from 'bandcamp-fetch';\n\nconst fan = bcfetch.fan;\n\nconst info = await fan.getInfo(...);\nconst collection = await fan.getCollection(...);\n```\n\n**Methods:**\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetInfo(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/fan/getInfo.mjs) ([output](examples/fan/getInfo_output.txt))\n\n\u003cp\u003eFetches info about a fan.\u003c/p\u003e\n\n**Params**\n\n- `params`: ([FanAPIGetInfoParams](docs/api/interfaces/FanAPIGetInfoParams.md))\n    - `username`: (string) (*optional*)\n    - `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n\n If `username` is not specified, result will be obtained for the user of the [session](#user-sessions) tied to the `BandcampFetch` instance.\n\n**Returns**\n\nPromise resolving to [Fan](docs/api/interfaces/Fan.md).\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetCollection(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/fan/getCollection.mjs) ([output](examples/fan/getCollection_output.txt))\n\n\u003cp\u003eFetches the list of albums and tracks in a fan's collection.\u003c/p\u003e\n\n**Params**\n\n- `params`: ([FanAPIGetItemsParams](docs/api/interfaces/FanAPIGetItemsParams.md))\n    - `target`: (string | [FanItemsContinuation](docs/api/interfaces/FanItemsContinuation.md)) (*optional*) if username (string) is specified, returns the first batch of items in the collection. To obtain further items, call the method again but, instead of username, pass `continuation` from the result of the first call. If there are no further items available, `continuation` will be `null`.\n    - `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n\nIf `target` is not specified, result will be obtained for the user of the [session](#user-sessions) tied to the `BandcampFetch` instance.\n\n**Returns**\n\nPromise resolving to ([FanPageItemsResult](docs/api/interfaces/FanPageItemsResult.md) | [FanContinuationItemsResult](docs/api/interfaces/FanContinuationItemsResult.md))\u003c[Album](docs/api/interfaces/Album.md) | [Track](docs/api/interfaces/Track.md)\u003e.\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetWishlist(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/fan/getWishlist.mjs) ([output](examples/fan/getWishlist_output.txt))\n\n\u003cp\u003eFetches the list of albums and tracks added to a fan's wishlist.\u003c/p\u003e\n\n**Params**\n\n- `params`: ([FanAPIGetItemsParams](docs/api/interfaces/FanAPIGetItemsParams.md))\n    - `target`: (string | [FanItemsContinuation](docs/api/interfaces/FanItemsContinuation.md)) (*optional*) if username (string) is specified, returns the first batch of items in the wishlist. To obtain further items, call the method again but, instead of username, pass `continuation` from the result of the first call. If there are no further items available, `continuation` will be `null`.\n    - `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n\nIf `target` is not specified, result will be obtained for the user of the [session](#user-sessions) tied to the `BandcampFetch` instance.\n\n**Returns**\n\nPromise resolving to ([FanPageItemsResult](docs/api/interfaces/FanPageItemsResult.md) | [FanContinuationItemsResult](docs/api/interfaces/FanContinuationItemsResult.md))\u003c[Album](docs/api/interfaces/Album.md) | [Track](docs/api/interfaces/Track.md)\u003e.\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetFollowingArtistsAndLabels(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/fan/getFollowingArtistsAndLabels.mjs) ([output](examples/fan/getFollowingArtistsAndLabels_output.txt))\n\n\u003cp\u003eFetches the list of artists and labels followed by a fan.\u003c/p\u003e\n\n**Params**\n\n- `params`: ([FanAPIGetItemsParams](docs/api/interfaces/FanAPIGetItemsParams.md))\n    - `target`: (string | [FanItemsContinuation](docs/api/interfaces/FanItemsContinuation.md)) (*optional*) if username (string) is specified, returns the first batch of artists and labels. To obtain further items, call the method again but, instead of username, pass `continuation` from the result of the first call. If there are no further items available, `continuation` will be `null`.\n    - `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n\nIf `target` is not specified, result will be obtained for the user of the [session](#user-sessions) tied to the `BandcampFetch` instance.\n\n**Returns**\n\nPromise resolving to ([FanPageItemsResult](docs/api/interfaces/FanPageItemsResult.md) | [FanContinuationItemsResult](docs/api/interfaces/FanContinuationItemsResult.md))\u003c[UserKind](docs/api/interfaces/UserKind.md)\u003e.\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetFollowingGenres(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/fan/getFollowingGenres.mjs) ([output](examples/fan/getFollowingGenres_output.txt))\n\n\u003cp\u003eFetches the list of genres followed by a fan.\u003c/p\u003e\n\nEach genre is actually a Bandcamp tag, so you can, for example, pass its `url` to `getReleases()` of the [Tag API](#tag-api).\n\n**Params**\n\n- `params`: ([FanAPIGetItemsParams](docs/api/interfaces/FanAPIGetItemsParams.md))\n    - `target`: (string | [FanItemsContinuation](docs/api/interfaces/FanItemsContinuation.md)) (*optional*) if username (string) is specified, returns the first batch of genres. To obtain further items, call the method again but, instead of username, pass `continuation` from the result of the first call. If there are no further items available, `continuation` will be `null`.\n    - `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n\nIf `target` is not specified, result will be obtained for the user of the [session](#user-sessions) tied to the `BandcampFetch` instance.\n\n**Returns**\n\nPromise resolving to ([FanPageItemsResult](docs/api/interfaces/FanPageItemsResult.md) | [FanContinuationItemsResult](docs/api/interfaces/FanContinuationItemsResult.md))\u003c[Tag](docs/api/interfaces/Tag.md)\u003e.\n\n---\n\u003c/details\u003e\n\n## Search API\n\nTo access the Search API:\n\n```\nimport bcfetch from 'bandcamp-fetch';\n\nconst search = bcfetch.search;\n\nconst albums = await search.albums(...);\nconst all = await search.all(...);\n```\n\n**Methods:**\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003eall(params) / artistsAndLabels(params) / albums(params) / tracks(params) / fans(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/search/search.mjs) ([output](examples/search/search_output.txt))\n\n- `all(params)`: search all item types\n- `artistsAndLabels(params)`: search artists and labels\n- `albums(params)`: search albums\n- `tracks(params)`: search tracks\n- `fans(params)`: search fans\n\n**Params**\n\n- `params`: ([SearchAPISearchParams](docs/api/interfaces/SearchAPISearchParams.md))\n    - `query`: (string)\n    - `page`: (number) (*optional*) 1 if omitted\n    - `albumImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n    - `artistImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)\n\n**Returns**\n\nPromise resolving to [SearchResults](docs/api/interfaces/SearchResults.md)\u0026lt;`T`\u0026gt;, where `T` depends on the item type being searched and can be one of:\n- Artist ([SearchResultArtist](docs/api/interfaces/SearchResultArtist.md))\n- Label ([SearchResultLabel](docs/api/interfaces/SearchResultLabel.md))\n- Album ([SearchResultAlbum](docs/api/interfaces/SearchResultAlbum.md))\n- Track ([SearchResultTrack](docs/api/interfaces/SearchResultTrack.md))\n- Fan ([SearchResultFan](docs/api/interfaces/SearchResultFan.md))\n\nYou can use the `type` property to determine the search result item type.\n\n---\n\u003c/details\u003e\n\n\n## Autocomplete API\n\nTo access the Autocomplete API:\n\n```\nimport bcfetch from 'bandcamp-fetch';\n\nconst autocomplete = bcfetch.autocomplete;\n\nconst suggestions = await autocomplete.getSuggestions(...);\n```\n\n**Methods:**\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003egetSuggestions(params)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/autocomplete/getSuggestions.mjs) ([output](examples/autocomplete/getSuggestions_output.txt))\n\n\u003cp\u003eFetches autocomplete suggestions for tags and locations, based on partial and full matches against `params.query`.\u003c/p\u003e\n\nThe `value` property of returned suggestions can be used to set the `location` or `tags` property (as the case may be) of `params.filters` that is passed into `getReleases()` of the [Tag API](#tag-api).\n\n**Params**\n\n- `params`: ([AutocompleteAPIGetSuggestionsParams](docs/api/interfaces/AutocompleteAPIGetSuggestionsParams.md))\n    - `query`: (string)\n    - `itemType`: ([AutocompleteItemType](docs/api/enums/AutocompleteItemType.md)) 'Tag' or 'Location'\n    - `limit`: (number) (*optional*) (only for `ItemType.Location`) the maximum number of results to return; 5 if omitted.\n\n**Returns**\n\n- If `params.itemType` is `AutocompleteItemType.Tag`, a Promise resolving to Array\u003c[AutocompleteTag](docs/api/interfaces/AutoCompleteTag.md)\u003e.\n- If `params.itemType` is `AutocompleteItemType.Location`, a Promise resolving to Array\u003c[AutocompleteLocation](docs/api/interfaces/AutocompleteLocation.md)\u003e.\n\n---\n\u003c/details\u003e\n\n## Stream API\n\nStream URLs returned by Bandcamp can sometimes be invalid (perhaps expired). Before playing a stream, you are recommended to test its URL and refresh it if necessary with the Stream API.\n\nTo access the Stream API:\n\n```\nimport bcfetch from 'bandcamp-fetch';\n\nconst stream = bcfetch.stream;\n\n// Test a stream URL\nconst streamURL = '...';\nconst testResult = await stream.test(streamUrl);\n\nif (!testResult.ok) {\n    const refreshedStreamURL = await stream.refresh(streamURL);\n}\n```\n\n**Methods:**\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003etest(url)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/stream/testAndRefresh.mjs) ([output](examples/stream/testAndRefresh_output.txt))\n\n\u003cp\u003eTests validity of the stream given by `url`.\u003c/p\u003e\n\n**Params**\n\n- `url`: (string) the URL of the stream to test\n\n**Returns**\n\nPromise resolving to [StreamTestResult](docs/api/interfaces/StreamTestResult.md):\n- `ok`: (boolean) whether the stream is valid\n- `status`: (number) the HTTP response status code returned by the test\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003erefresh(url)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n[**Example**](examples/stream/testAndRefresh.mjs) ([output](examples/stream/testAndRefresh_output.txt))\n\n\u003cp\u003eRefreshes a stream URL.\u003c/p\u003e\n\n**Params**\n\n- `url`: (string) the URL of the stream to refresh\n\n**Returns**\n\nPromise resolving to the refreshed URL of the stream or `null` if no valid result was obtained.\n\n---\n\u003c/details\u003e\n\n# Rate Limiting\n\nEach `BandcampFetch` instance comes with a rate limiter, which limits the number of requests made within a specific time period.\n\nRate limiting is useful when you need to make a large number of queries and don't want to run the risk of getting rejected by the server for making too many requests within a short time interval. If you get a '429 Too Many Requests' error, then you should consider using the rate limiter.\n\nEach API has a limiter-enabled counterpart which you can access in the following manner:\n\n```\nimport bcfetch from 'bandcamp-fetch';\n\n// Album API - no limiter enabled\nconst albumAPI = bcfetch.album;\n\n// Album API - limiter enabled\nconst limiterAlbumAPI = bcfetch.limiter.album;\n```\n\n[**Example**](examples/limiter/limiter.mjs) ([output](examples/limiter/limiter_output.txt))\n\nThe library uses [Bottleneck](https://www.npmjs.com/package/bottleneck) for rate limiting. You can configure the rate limiter like this:\n\n```\nbcfetch.limiter.updateSettings({\n    maxConcurrent: 10,  // default: 5\n    minTime: 100        // default: 200\n});\n```\n\n`updateSettings()` is just a passthrough function to Bottleneck. Check the [Bottleneck doc](https://www.npmjs.com/package/bottleneck#docs) for the list of options you can set.\n\n# Cache\n\nEach `BandcampFetch` instance has an in-memory cache for two types of data (as defined by [CacheDataType](docs/api/enums/CacheDataType.md)):\n\n1. `CacheDataType.Page` - pages fetched during scraping\n2. `CacheDataType.Constants` - image formats and discover options\n\nTo access the cache:\n\n```\nimport bcfetch, { CacheDataType } from 'bandcamp-fetch';\n\nconst cache = bcfetch.cache;\n\ncache.setTTL(CacheDataType.Page, 500);\n```\n\n**Methods:**\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003esetTTL(type, ttl)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n\u003cp\u003eSets the expiry time, in seconds, of cache entries for the given data type.\u003c/p\u003e\n\n**Params**\n\n- `type`: ([CacheDataType](docs/api/enums/CacheDataType.md))\n- `TTL`: (number) expiry time in seconds (default: 300 for `CacheDataType.Page` and 3600 for `CacheDataType.Constants`)\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003esetMaxPages(maxPages)\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n\u003cp\u003eSets the maximum number of pages that can be stored in the cache. A negative value means unlimited. Default: 10.\u003c/p\u003e\n\n**Params**\n\n- `maxPages`: (number)\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003eclear([type])\u003c/code\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n\u003cp\u003eClears the cache entries for the specified data type (or all entries if no data type specified).\u003c/p\u003e\n\n**Params**\n\n- `type`: ([CacheDataType](docs/api/enums/CacheDataType.md)) (*optional*)\n\n---\n\u003c/details\u003e\n\n\n# Changelog\n\n2.0.0 ([breaking changes](docs/changes-1.x-2.x.md)!)\n- Revise API to reflect Bandcamp changes\n- Add `lyrics` property to `Track`\n- Add `id` property to `Album` and `Track`\n- Add `slug` property to categories returned by `DiscoveryAPI.getAvailableOptions()`\n- Parse missing discog items ([#8](https://github.com/patrickkfkan/bandcamp-fetch/issues/8))\n\n1.2.1\n- Fix `duration` not returned in result of `TrackAPI::getInfo()` ([#7](https://github.com/patrickkfkan/bandcamp-fetch/issues/7))\n\n1.2.0\n- Add Stream API for testing and refreshing stream URLs\n\n1.1.1\n- Fix exports\n\n1.1.0\n- Add support for user sessions through cookies. This means you can access your private collection and high-quality MP3 streams of purchased media.\n- Add ability to create multiple `BandcampFetch` instances\n\n1.0.2\n- Improve parsing of album track info\n\n1.0.1\n- Fix limiter throwing private access errors\n\n1.0.0 (breaking changes!)\n- Move to TypeScript\n- Package as ESM + CJS hybrid module\n- Restructure API\n- Remove `safe-eval` dependency\n\n0.3.1-b.1\n- Add `getFanCollection()` function\n\n0.3.0-b.1\n- Add fan functions\n\n0.2.2-b.1\n- Add `itemType` option to search params\n\n0.2.1-b.20211020b\n- Fix URL sometimes null in result of `getArtistOrLabelInfo()`\n\n0.2.1-b.20211020\n- Improve data fetching in `getArtistOrLabelInfo()`\n\n0.2.0-b.20211020\n- Adapt to Bandcamp changes since last version\n- Add `publisher` and `label` to data fetched by `getAlbumInfo()` and `getTrackInfo()`\n- Add `labelId` to data fetched by `getArtistOrLabelInfo(labelUrl)`\n- Add `labelId` option to `getArtistOrLabelInfo()` for artist URLs\n\n...(no changelog for earlier versions due to laziness)\n\n# License\n\nMIT","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatrickkfkan%2Fbandcamp-fetch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpatrickkfkan%2Fbandcamp-fetch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatrickkfkan%2Fbandcamp-fetch/lists"}