Automated SoundCloud song metadata downloader using GitHub Actions. Extracts the SoundCloud API token and downloads song descriptions for a specified user's tracks.
go to the folder runner and use the terminal
$ npm run test
This project uses GitHub Actions to:
- Extract the SoundCloud
client_idtoken by monitoring network requests - Fetch all tracks from a specified SoundCloud user
- Download metadata (title, description, etc.) for each track
- Process and format playlist descriptions into organized text files
- Upload formatted playlists as a workflow artifact
Perfect for backing up your SoundCloud playlists, creating readable tracklists, or archiving DJ mixes and radio shows.
.
├── .github/workflows/
│ └── main.yml # GitHub Actions workflow
├── soundcloud-token-getter/
│ ├── index.js # Playwright script to extract client_id
│ ├── check-token.js # Script to validate existing token
│ ├── package.json # Node.js dependencies
│ └── client_id.txt # Output file (generated, cached)
├── soundcloud-downloader/
│ ├── download.js # Script to fetch track metadata
│ ├── package.json # Node.js dependencies
│ └── soundcloud-jsons/ # Downloaded track data (generated)
├── artifact-processing/
│ ├── index.js # Script to format playlists
│ ├── corrections.json # Manual typo corrections
│ ├── package.json # Node.js dependencies
│ └── (processed files) # Generated in workflow
├── artifact-preview/
│ ├── .gitkeep # Preserves directory in git
│ ├── soundcloud-json/ # Local preview of downloaded JSON files
│ └── out-playlists/ # Formatted playlists (generated)
├── runner/
│ └── package.json # Test and cleanup scripts
├── setup-act/
│ └── setup-act.sh # Script to install 'act' for local testing
└── README.md # This file
- Node.js 20 or higher
- npm
- Clone the repository:
git clone https://github.com/chepe263/github-actions-soundcloud-download.git
cd github-actions-soundcloud-download- Install dependencies:
# Install token getter dependencies
cd soundcloud-token-getter
npm install
# Install downloader dependencies
cd ../soundcloud-downloader
npm install
# Install processing dependencies
cd ../artifact-processing
npm install- Install Playwright browser (from soundcloud-token-getter directory):
cd soundcloud-token-getter
npx playwright install webkit --with-depsExtract the SoundCloud client_id:
cd soundcloud-token-getter
npm run get-tokenDownload track metadata for a SoundCloud user:
cd ../soundcloud-downloader # if coming from soundcloud-token-getter
SOUNDCLOUD_USER=username npm run download
# or
node download.js usernameThe track data will be saved to soundcloud-downloader/tracks/.
Process playlists into formatted text files:
cd ../artifact-processing
npm startThe formatted playlists will be saved to artifact-preview/out-playlists/ organized by year and month.
The workflow automatically runs on:
- Push to
masterormainbranch - Pull requests to
masterormainbranch - Manual trigger via workflow_dispatch
The workflow will:
- Set up Node.js environment
- Extract the SoundCloud
client_idtoken - Download track metadata for the specified SoundCloud user
- Process playlists into formatted text files organized by year/month
- Upload formatted playlists as a workflow artifact
You can download the artifact from the Actions tab in your GitHub repository after the workflow completes.
To specify which SoundCloud user's tracks to download:
Option 1: Manual workflow trigger with input
- Go to Actions tab in GitHub
- Select "Download SoundCloud Tracks" workflow
- Click "Run workflow"
- Enter the SoundCloud username
- Click "Run workflow"
Option 2: Set repository variable
- Go to Settings → Secrets and variables → Actions → Variables
- Create a new variable named
SOUNDCLOUD_USER - Set the value to the SoundCloud username
- The workflow will use this automatically
Option 3: Hardcode in workflow file
Edit .github/workflows/main.yml and change the default value to the desired username (currently set to euphonicsessions).
After the workflow completes:
- Go to the Actions tab in your repository
- Click on the completed workflow run
- Scroll down to the "Artifacts" section
- Download the
soundcloud-playlists-*artifact (ZIP file) - Extract the ZIP to access formatted playlist text files organized by year and month
The playlists are formatted with:
- Track numbers followed by artist and title
- Remix/label information in parentheses
- Special tags like [TRACK OF THE MONTH] preserved
- Monthly episodes:
YYYY-MM-MonthName.txt - Best Of episodes:
YYYY-13-December (Best of YYYY).txt
To test the GitHub Actions workflow locally before pushing:
- Install and run via the runner scripts:
cd runner
npm run cleanup # Clean previous test files
npm test # Run workflow locally with act (--bind mode)- Or manually install
act:
./setup-act/setup-act.sh- Run the workflow with bind mount:
act workflow_dispatch --bind --container-architecture linux/amd64The --bind flag ensures files created in the Docker container persist to your local filesystem in artifact-preview/ and soundcloud-downloader/tracks/.
Note: The artifact upload step will fail in local testing (expected behavior), but all track files will still be downloaded and available locally.
The runner/ directory contains helpful npm scripts for local development and testing:
cd runner
# Run full workflow locally (with Docker/act)
npm test
# Run workflow steps directly (without Docker)
npm run test:local
# Clean generated files (keeps .gitkeep)
npm run cleanup
# Clean everything including node_modules
npm run cleanup:allnpm test- Runs the GitHub Actions workflow locally using act with bind mountnpm run test:push- Tests the workflow with push triggernpm run test:local- Executes workflow steps directly on host (no Docker)npm run cleanup- Removes tracks/, out-playlists/, and soundcloud-json/* files (preserves client_id.txt)npm run cleanup:all- Full cleanup including all node_modules directoriesnpm run zip- Creates a zip of all formatted playlists
- Token Validation: Checks if an existing
client_id.txtis valid by testing it against the SoundCloud API - Token Extraction: If no valid token exists, launches a headless WebKit browser using Playwright, navigates to https://soundcloud.com/, monitors network requests, and extracts the
client_idparameter from API calls - User Resolution: Uses the SoundCloud API with the extracted token to resolve the username to a user ID
- Track Fetching: Fetches all tracks for the specified user via the SoundCloud API v2
- Metadata Download: For each track, downloads the title, description, artwork URL, duration, play count, and other metadata
- File Creation: Saves each track as an individual JSON file plus a
_summary.jsonindex file - Playlist Processing: Parses track descriptions, formats tracklists, and organizes into year/month text files
- Artifact Upload: In GitHub Actions, packages formatted playlists as a downloadable artifact
- Token Caching: The
client_idis cached inclient_id.txtand reused if still valid, skipping Playwright browser installation - Apt Package Caching: System dependencies are cached to speed up Playwright browser installation when needed
- Bind Mounting: When testing locally with act,
--bindmode ensures files persist to the host filesystem - Artifact Preview: Files are copied to
artifact-preview/directory for local inspection before upload
npm start- Run the token extraction scriptnpm run get-token- Alias for npm startnpm run check-token- Validate existing token against SoundCloud API
npm run download- Download track metadata (requires SOUNDCLOUD_USER env variable)
npm start- Process playlists from JSON files into formatted text filesnpm run cleanup- Remove generated out-playlists/ directory
npm test- Run workflow locally with act (bind mount mode)npm run test:push- Test workflow with push triggernpm run test:local- Run workflow steps directly without Dockernpm run zip- Create zip of all formatted playlistsnpm run cleanup- Remove generated files (preserves client_id.txt for caching)npm run cleanup:all- Full cleanup including node_modules
Each track is saved as a JSON file containing:
id- SoundCloud track IDtitle- Track titledescription- Track description textpermalink_url- Full SoundCloud URLduration- Duration in millisecondsplayback_count- Number of playslikes_count- Number of likescomment_count- Number of commentscreated_at- Upload dategenre- Genre tagtag_list- Space-separated tagsartwork_url- Cover art URL
A _summary.json file is also created with an index of all downloaded tracks.
Playlists are organized by year and month in out-playlists/:
out-playlists/
├── 2015/
│ ├── 2015-01-January.txt
│ ├── 2015-02-February.txt
│ └── 2015-13-December (Best of 2015).txt
├── 2016/
│ └── ...
└── ...
Each playlist file contains:
- Header with episode title and SoundCloud URL
- Formatted tracklist with proper numbering
- Artist names and track titles
- Remix/label information in parentheses
- Special tags preserved (e.g., [TRACK OF THE MONTH])
Best Of Episodes:
- Use month number
13to sort after December - Filename format:
YYYY-13-December (Best of YYYY).txt - Separate header format for "Best Of" compilations
ISC