/install 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)
wsmodule at/opt/homebrew/lib/node_modules/openclaw/node_modules/ws- Node.js runtime
Authentication Flow
Beatport uses a dual-auth system:
- account.beatport.com — Django session (
sessionidcookie) - www.beatport.com — NextAuth (
__Secure-next-auth.session-tokencookie)
Login Steps
- Navigate to
https://account.beatport.com/via CDPPage.navigate - Fill username/password via
Runtime.evaluate(use native input setters to bypass React controlled inputs) - Submit the login form
- 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();
});
- Verify login:
Account menubutton should appear in navbar (noCreate Account or Log Inbutton)
Key URLs
| Page | URL | Purpose |
|---|---|---|
| Cart | https://www.beatport.com/cart |
Items pending purchase |
| Library | https://www.beatport.com/library |
Purchased tracks (may show Upgrade for free accounts) |
| Downloads | https://www.beatport.com/library/downloads |
Download queue |
| Checkout | https://www.beatport.com/checkout |
Payment 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/\x3Cid>
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/version → webSocketDebuggerUrl.
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=\x3CJWT_TOKEN>
The token is single-use and expires quickly. Always capture fresh from events.
Download URL Format
https://zips.beatport.com/v1/download?token=\x3CJWT_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: \x3Ccookies>" \
"https://www.beatport.com/_next/data/\x3CbuildId>/en/library/downloads.json" \
| jq -r '.pageProps.accessToken'
Library Data
curl -s -H "Cookie: \x3Ccookies>" \
"https://www.beatport.com/_next/data/\x3CbuildId>/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
- Cross-domain navigation fails with
Page.navigate— Uselocation.href = "..."viaRuntime.evaluateinstead - 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 })); - Node.js string escaping in
-e— UseString.raw\...`template literals, or write code to a file and run withnode file.js` - Free account download limit — 20 downloads per track. "Unlimited re-downloads" requires Beatport Streaming subscription
- CDP exec timeout — openclaw kills long-running node processes (~10s). Keep CDP operations short; use
background: true+process pollfor longer waits curlpath — 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
- 确保已安装 OpenClaw(本地或 Docker 部署)
- 在对话框中输入安装命令:
/install beatport-dl-with-browser-tool - 安装完成后,直接呼叫该 Skill 的名称或使用
/beatport-dl-with-browser-tool触发 - 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
Beatport Download via Browser Tool 是什么?
Download purchased tracks from Beatport using the openclaw headless browser tool (CDP). Handles login, authentication via NextAuth, enabling downloads in hea... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 56 次。
如何安装 Beatport Download via Browser Tool?
在 OpenClaw 或 Claude Code 对话框中运行命令「/install beatport-dl-with-browser-tool」即可一键安装,无需额外配置。
Beatport Download via Browser Tool 是免费的吗?
是的,Beatport Download via Browser Tool 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。
Beatport Download via Browser Tool 支持哪些平台?
Beatport Download via Browser Tool 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。
谁开发了 Beatport Download via Browser Tool?
由 esanle(@esanle)开发并维护,当前版本 v1.0.0。