beatport-dl-with-browser-tool

Download purchased tracks from Beatport using the openclaw headless browser tool (CDP). Handles login, authentication via NextAuth, enabling downloads in headless Chrome, and saving files locally. Use when the user asks to download music, tracks, or files from Beatport, or manage their Beatport purchases/library. Triggers on phrases like "download from beatport", "beatport download", "download my tracks", "get my beatport music".

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "beatport-dl-with-browser-tool" with this command: npx skills add esanle/beatport-dl-with-browser-tool

Beatport Download via Browser Tool

Download purchased Beatport tracks through the openclaw headless browser using CDP (Chrome DevTools Protocol).

Prerequisites

  • openclaw browser running on 127.0.0.1:9222
  • Beatport credentials (username + password)
  • ws module at /opt/homebrew/lib/node_modules/openclaw/node_modules/ws
  • Node.js runtime

Authentication Flow

Beatport uses a dual-auth system:

  1. account.beatport.com — Django session (sessionid cookie)
  2. www.beatport.com — NextAuth (__Secure-next-auth.session-token cookie)

Login Steps

  1. Navigate to https://account.beatport.com/ via CDP Page.navigate
  2. Fill username/password via Runtime.evaluate (use native input setters to bypass React controlled inputs)
  3. Submit the login form
  4. On the www.beatport.com tab, sign in via NextAuth:
// In browser context on www.beatport.com
fetch("/api/auth/csrf").then(r => r.json()).then(csrf => {
  const fd = new URLSearchParams();
  fd.append("csrfToken", csrf.csrfToken);
  fd.append("username", "USER");
  fd.append("password", "PASS");
  fd.append("callbackUrl", "https://www.beatport.com/");
  // Create hidden form and submit (fetch redirect fails cross-origin)
  const form = document.createElement("form");
  form.method = "POST";
  form.action = "/api/auth/signin/beatport";
  form.style.display = "none";
  for (const [k, v] of Object.entries(Object.fromEntries(fd))) {
    const inp = document.createElement("input");
    inp.type = "hidden"; inp.name = k; inp.value = v;
    form.appendChild(inp);
  }
  document.body.appendChild(form);
  form.submit();
});
  1. Verify login: Account menu button should appear in navbar (no Create Account or Log In button)

Key URLs

PageURLPurpose
Carthttps://www.beatport.com/cartItems pending purchase
Libraryhttps://www.beatport.com/libraryPurchased tracks (may show Upgrade for free accounts)
Downloadshttps://www.beatport.com/library/downloadsDownload queue
Checkouthttps://www.beatport.com/checkoutPayment page

Note: /my-beatport/downloads and /my-beatport/collection return 404. The correct paths are /library and /library/downloads.

Enabling Downloads in Headless Chrome

Headless Chrome cancels downloads by default. Enable via CDP on the browser-level WebSocket:

// Browser-level WS: ws://127.0.0.1:9222/devtools/browser/<id>
ws.send(JSON.stringify({
  id: 1,
  method: "Browser.setDownloadBehavior",
  params: {
    behavior: "allowAndName",
    downloadPath: "/path/to/download/dir/",
    eventsEnabled: true
  }
}));

Get browser ID from http://127.0.0.1:9222/json/versionwebSocketDebuggerUrl.

Downloading Tracks

Step 1: Add tracks to download queue

On /library, each track has a re-download icon (svg[data-testid='icon-re-download']). Click each one to add to the download queue:

var icons = document.querySelectorAll("svg[data-testid='icon-re-download']");
icons.forEach(function(icon, i) {
  setTimeout(function() { icon.closest("button, div").click(); }, i * 500);
});

Step 2: Download from queue page

Navigate to /library/downloads. All queued tracks appear with a "Download All" button.

Step 3: Click Download All

Enable browser downloads first (see above), then click:

var btn = [...document.querySelectorAll("button")].find(b => b.innerText.includes("Download All"));
if (btn) btn.click();

The download arrives as a zip file (e.g. beatport_tracks_2026-04.zip).

Step 4: Unzip and clean up

cd /path/to/download/dir
unzip -o beatport_tracks_*.zip -d tmp/
mv tmp/*.mp3 .
rm -rf tmp/ beatport_tracks_*.zip

Download URL Format

https://zips.beatport.com/v1/download?token=<JWT_TOKEN>

The token is single-use and expires quickly. Always capture fresh from events.

Download URL Format

https://zips.beatport.com/v1/download?token=<JWT_TOKEN>

The token is single-use and expires quickly. Always capture it fresh from the Page.downloadWillBegin event.

API Access

Access Token

curl -s -H "Cookie: <cookies>" \
  "https://www.beatport.com/_next/data/<buildId>/en/library/downloads.json" \
  | jq -r '.pageProps.accessToken'

Library Data

curl -s -H "Cookie: <cookies>" \
  "https://www.beatport.com/_next/data/<buildId>/en/library.json" \
  | jq '.pageProps.dehydratedState.queries[].state.data.results[] | {name, id, artists}'

Build ID

curl -s "https://www.beatport.com/" | grep -o '"buildId":"[^"]*"' | head -1

Current buildId (subject to change): PWoDyRo_P5V8lNYu_92bX

Common Pitfalls

  1. Cross-domain navigation fails with Page.navigate — Use location.href = "..." via Runtime.evaluate instead
  2. React controlled inputs don't respond to .value = — Use native input value setter:
    var input = document.querySelector("input[name=username]");
    var nativeSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value").set;
    nativeSetter.call(input, "username");
    input.dispatchEvent(new Event("input", { bubbles: true }));
    
  3. Node.js string escaping in -e — Use String.raw\...`template literals, or write code to a file and run withnode file.js`
  4. Free account download limit — 20 downloads per track. "Unlimited re-downloads" requires Beatport Streaming subscription
  5. CDP exec timeout — openclaw kills long-running node processes (~10s). Keep CDP operations short; use background: true + process poll for longer waits
  6. curl path — Use /usr/bin/curl, not /opt/homebrew/bin/curl (may not exist)

CDP Helper Pattern

Write scripts to files to avoid shell escaping issues:

// scripts/beatport-cdp.js
const WS = require("/opt/homebrew/lib/node_modules/openclaw/node_modules/ws");
const http = require("http");

function getPage(filter) {
  return new Promise((resolve) => {
    http.get("http://127.0.0.1:9222/json", (res) => {
      let body = "";
      res.on("data", (c) => body += c);
      res.on("end", () => {
        const pages = JSON.parse(body).filter(p => p.type === "page");
        resolve(filter ? pages.find(filter) || pages[0] : pages[0]);
      });
    });
  });
}

function cdpEval(ws, expression) {
  return new Promise((resolve) => {
    ws.send(JSON.stringify({ id: Date.now(), method: "Runtime.evaluate", params: { expression, returnByValue: true } }));
    ws.on("message", (m) => {
      const d = JSON.parse(m.toString());
      if (d.id && d.result) { resolve(d.result); }
    });
  });
}

async function screenshot(ws, path) {
  return new Promise((resolve) => {
    ws.send(JSON.stringify({ id: Date.now(), method: "Page.captureScreenshot", params: { format: "png" } }));
    ws.on("message", (m) => {
      const d = JSON.parse(m.toString());
      if (d.id && d.result && d.result.data) {
        require("fs").writeFileSync(path, Buffer.from(d.result.data, "base64"));
        resolve();
      }
    });
  });
}

module.exports = { getPage, cdpEval, screenshot };

Format Compatibility

  • CDJ-2000: MP3 or WAV
  • Beatport download options: MP3, WAV, AIFF, FLAC
  • Default is MP3; select WAV/AIFF on cart page or account settings if needed for CDJ compatibility

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

通义晓蜜 - 智能外呼

触发阿里云晓蜜外呼机器人任务,自动批量拨打电话。适用于批量外呼、客户回访、满意度调查、简历筛查约面试等场景。可从前置工具或节点获取外呼名单。

Registry SourceRecently Updated
General

Letterboxd Watchlist

Scrape a public Letterboxd user's watchlist into a CSV/JSONL list of titles and film URLs without logging in. Use when a user asks to export, scrape, or mirror a Letterboxd watchlist, or to build watch-next queues.

Registry SourceRecently Updated
General

Seedance Video Generation

Generate AI videos using ByteDance Seedance. Use when the user wants to: (1) generate videos from text prompts, (2) generate videos from images (first frame, first+last frame, reference images), or (3) query/manage video generation tasks. Supports Seedance 1.5 Pro (with audio), 1.0 Pro, 1.0 Pro Fast, and 1.0 Lite models.

Registry SourceRecently Updated
4.2K17jackycser
General

Universal Skills Manager

The master coordinator for AI skills. Discovers skills from multiple sources (SkillsMP.com, SkillHub, and ClawHub), manages installation, and synchronization...

Registry SourceRecently Updated