Skip to content

Fix DownloadCollection.user.js for new Bandcamp collection page (v1.5)#39

Open
rmilev wants to merge 1 commit into
RyanBluth:masterfrom
rmilev:fix/download-collection-new-api
Open

Fix DownloadCollection.user.js for new Bandcamp collection page (v1.5)#39
rmilev wants to merge 1 commit into
RyanBluth:masterfrom
rmilev:fix/download-collection-new-api

Conversation

@rmilev

@rmilev rmilev commented Jun 19, 2026

Copy link
Copy Markdown

Summary

Bandcamp changed the collection page some time in 2025/2026 and the existing DownloadCollection.user.js no longer works: scanning finds 0–20 items, Auto-scan never completes, and the "Retry pagination" button throws.

This PR rewires the script around Bandcamp's current page model:

  • The collection grid now ships only the first ~20 items in the DOM behind a view all N items button. The rest live behind POST /api/fancollection/1/collection_items (request body: {fan_id, older_than_token, count}; response: {items, redownload_urls, last_token, more_available, ...}).
  • window.CollectionGrids.collection.paginate() no longer exists, so the old "Retry pagination" button is dead code.
  • The album/track/download metadata is embedded server-side in document.querySelector('#pagedata').dataset.blob (item_cache.collection, collection_data.{redownload_urls,last_token,item_count}, fan_data.fan_id).

What changed

  • Seed from #pagedata on script load (fan id, initial item cache, initial redownload URLs, initial pagination cursor, total item count).
  • fetchAllItems() pages through the fancollection API in 20-item batches with a ~150ms gap between requests — without the gap Bandcamp returns more_available: false on the second call. Verified end-to-end on a 416-item collection.
  • itemKey(item) rebuilds the {type_char}{id} key for items returned by the API (the response uses an array, not the keyed-object format that #pagedata.item_cache uses).
  • findDownloadUrl(item) looks up redownload URLs by {sale_item_type}{sale_item_id} rather than always assuming a p prefix — Bandcamp keys 'p' for packages, 'a' for albums, 't' for tracks.
  • Scan albums now reads from the cached items instead of scraping .collection-item-container (which only ever contains the first batch).
  • Auto-scan albums calls fetchAllItems and then triggers Scan, instead of the old click-then-scroll loop that doesn't terminate on the new page.
  • Retry pagination button removed — its paginate() call would throw.
  • Layout: download-all / download-selected and the range row are split into separate .controls rows so they group logically.
  • CSS: force readable button/input colors — Bandcamp's site styles now leave them effectively invisible.
  • @version bumped to 1.5.

Test plan

  • Fresh load on bandcamp.com/<your-username> with a 416-item collection
  • Auto-scan ticks 40 / 416 → 60 / 416 → ... → 416 / 416
  • Scan reports all downloadable items (matches non-subscription count)
  • Generated download URLs match Bandcamp's own download?from=&payment_id=&sig=&sitem_id= format
  • Download all / Download selected / Download range still open the right tabs

The collection page changed shape in 2025/2026: it now ships only the
first ~20 items in the DOM behind a "view all N items" button and
loads the rest via the /api/fancollection/1/collection_items endpoint.
window.CollectionGrids.collection.paginate() no longer exists, the
"Retry pagination" button would throw, and the old DOM-scroll auto-scan
never completes.

Rewire the script to:
  * seed item state from the page's #pagedata blob (item_cache,
    redownload_urls, last_token, fan_id, item_count),
  * page through the fancollection API in 20-item batches (with a
    small delay — Bandcamp returns more_available:false on rapid
    back-to-back requests) to load the rest,
  * key items by {sale_item_type_char}{sale_item_id} because the API
    response returns items as an array rather than a keyed object,
  * look up redownload URLs by the item's sale_item_type prefix
    (Bandcamp keys them 'p'/'a'/'t', not just 'p'),
  * drop the now-broken "Retry pagination" button,
  * split the Download/Range controls into two rows so they group
    logically, and
  * force readable button/input colors — Bandcamp's site CSS now
    leaves them invisible.

Tested against a 416-item collection: all items load and all
purchased items resolve to their download URLs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant