API Guide
The SoundCloud API provides endpoints for authentication, track upload and playback, social features, and search. This guide covers common integration patterns with code examples. For detailed endpoint specifications, see the API Explorer.
Key Facts
- Base URL:
https://api.soundcloud.com - Auth URL:
https://secure.soundcloud.com - Auth method: OAuth 2.1 with PKCE
- Token expiry: ~1 hour
- Token refresh: single-use refresh tokens
- Required header:
Authorization: OAuth ACCESS_TOKEN - Supported audio formats: AIFF, WAVE, FLAC, OGG, MP2, MP3, AAC, AMR, WMA
Prerequisites
All API usage requires a registered application:
- Register your app
- Obtain your
client_idandclient_secret - Authenticate (required for endpoints that access user resources)
Authentication
SoundCloud uses OAuth 2.1 for authentication. PKCE is required for the authorization code exchange.
If migrating from OAuth 2.0, see the differences in the RFC.
Supported Authorization Flows
| Flow | User Resources Access | Server-side Implementation |
|---|---|---|
| Authorization Code | Yes | Yes |
| Client Credentials | No | Yes |
- Authorization Code: For applications that perform actions on a user's behalf (upload, access private content). Requires user consent.
- Client Credentials: For applications accessing public resources only (search, playback, URL resolution). No user session required.
Sign in with SoundCloud
The Connect with SoundCloud button enables one-click OAuth registration and sign-in. After authorization, the application gains access to the user's account for uploading, playlist creation, and other user-scoped actions.
Authorization Code Flow
1. Redirect User to Authorization URL
Construct the authorization URL with the required parameters and redirect the user's browser to it. This step runs on the front-end.
# open in the browser
https://secure.soundcloud.com/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&code_challenge=CODE_CHALLENGE&code_challenge_method=S256&state=STATE
Parameters:
- YOUR_CLIENT_ID: The client ID from application registration.
- YOUR_REDIRECT_URI: The URI from application registration. The user is redirected here after authentication.
- CODE_CHALLENGE: A PKCE code challenge. See What is PKCE? and PKCE generator sandbox.
- STATE: A random string for CSRF protection. Verify this nonce after retrieving the token.
2. User Authorization
The user is redirected to SoundCloud to log in and approve the authorization request.
3. Obtain Access Token
After approval, SoundCloud redirects to your redirect_uri with a code query parameter. Exchange this code for an access token:
curl -X POST "https://secure.soundcloud.com/oauth/token" \
-H "accept: application/json; charset=utf-8" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=authorization_code" \
--data-urlencode "client_id=YOUR_CLIENT_ID" \
--data-urlencode "client_secret=YOUR_CLIENT_SECRET" \
--data-urlencode "redirect_uri=YOUR_REDIRECT_URI" \
--data-urlencode "code_verifier=YOUR_PKCE_GENERATED_CODE_VERIFIER" \
--data-urlencode "code=YOUR_CODE"
Parameters:
- YOUR_CLIENT_ID, YOUR_CLIENT_SECRET: From application registration.
- YOUR_PKCE_GENERATED_CODE_VERIFIER: Generated by your application during step 1.
- YOUR_REDIRECT_URI: Must match the URI used in the authorization request exactly.
- YOUR_CODE: The authorization code received from the authorization server.
4. Store and Use Tokens
The response contains access_token, refresh_token, expires_in, and scope. Store these values associated with the user. Use the access_token for subsequent API requests and the refresh_token to renew expired tokens.
curl "https://api.soundcloud.com/me" \
-H "accept: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN"
Client Credentials Token Exchange Flow
The Client Credentials flow authenticates an application (not a user) to access public resources. Send client_id and client_secret via HTTP Basic authentication to obtain an access token.
curl -X POST "https://secure.soundcloud.com/oauth/token" \
-H "accept: application/json; charset=utf-8" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Authorization: Basic Base64(client_id:client_secret)" \
--data-urlencode "grant_type=client_credentials"
# If your client_id is "my_client_id" and client_secret is "my_client_secret"
# The concatenated string would be "my_client_id:my_client_secret"
# The Base64 encoded string of "my_client_id:my_client_secret" is "bXlfY2xpZW50X2lkOm15X2NsaWVudF9zZWNyZXQ="
For the client_credentials grant type, only HTTP Basic authentication (Authorization: Basic ...) is supported. Sending credentials in the request body is not supported.
The response contains access_token, refresh_token, expires_in, and scope. Store and reuse the token; use refresh_token to renew expired tokens.
Constraints — Client Credentials token rate limits: - 50 tokens per 12 hours per application - 30 tokens per 1 hour per IP address - Reuse tokens across service instances - Implement the refresh token flow to stay within limits
Note: All clients are currently treated as confidential rather than public, meaning a secret is required to obtain a token.
Refreshing Tokens
Access tokens expire after approximately 1 hour. Use the refresh_token to obtain a new access token. Each refresh token is single-use.
Note: All clients are currently treated as confidential rather than public, meaning a secret is required to obtain a token.
curl -X POST "https://secure.soundcloud.com/oauth/token" \
-H "accept: application/json; charset=utf-8" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=refresh_token" \
--data-urlencode "client_id=YOUR_CLIENT_ID" \
--data-urlencode "client_secret=YOUR_CLIENT_SECRET" \
--data-urlencode "refresh_token=YOUR_TOKEN"
Mobile and Desktop Applications
Mobile and desktop applications use the same authorization code flow as web applications. Use a custom protocol scheme for the redirect_uri (e.g., my-app://soundcloud/callback).
For mobile devices, add display=popup to the authorization URL query string to use the mobile-optimized connect screen.
Signing Out
To sign out the user, send the access_token as follows:
curl -X POST "https://secure.soundcloud.com/sign-out" \
-H "Content-Type: application/json" \
-d '{"access_token": "ACCESS_TOKEN"}'
Error responses have the following format: ```
Error:
{ "error": "XXXX" } ```
Sign-out error details:
| Response | Status | Description |
|---|---|---|
| bad_request | 400 | body is missing access token |
| unauthorized | 401 | this token is associated with a session that is already invalid |
Accessing Resources
Every API request requires an Authorization header:
-H "Authorization: OAuth ACCESS_TOKEN"
Requests without this header return 401 Unauthorized. See the Authentication section for supported auth methods.
Getting Information about the Authenticated User
The /me endpoint returns profile information for the authenticated user.
curl "https://api.soundcloud.com/me" \
-H "accept: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN"
Uploading Tracks
The API supports uploading, managing, and sharing tracks. Supported audio formats: AIFF, WAVE, FLAC, OGG, MP2, MP3, AAC, AMR, WMA.
Uploading Audio Files
Send a POST request with multipart/form-data to the /tracks endpoint.
Maximum request body size: 500MB.
curl -X POST "https://api.soundcloud.com/tracks" \
-H "accept: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN" \
-H "Content-Type: multipart/form-data" \
-F "track[title]=YOUR_TITLE" \
-F "track[asset_data]=@PATH_TO_A_FILE"
On success, the track is queued for encoding.
Updating Metadata
To update track metadata, send a PUT request to the /tracks/:id endpoint with the properties to update.
Track artwork can be updated via the artwork_data parameter. The audio file cannot be updated after upload.
# Multipart request
curl -X PUT "https://api.soundcloud.com/tracks/TRACK_ID" \
-H "accept: application/json; charset=utf-8" \
-H "Content-Type: multipart/form-data" \
-H "Authorization: OAuth ACCESS_TOKEN" \
-F "track[title]=YOUR_TITLE" \
-F "track[description]=YOUR_DESCRIPTION" \
-F "track[artwork_data]=@PATH_TO_FILE"
# JSON request
curl -X PUT "https://api.soundcloud.com/tracks/TRACK_ID" \
-H "accept: application/json; charset=utf-8" \
-H "Content-Type: application/json" \
-H "Authorization: OAuth ACCESS_TOKEN" \
-d '{"track":{"title":"NEW TITLE"}}'
Creating Playlists
Playlists group tracks for sharing. A track can belong to multiple playlists. Playlists can be public or private.
Create a playlist by sending a POST request to /playlists with playlist metadata and a list of track IDs.
curl -X POST "https://api.soundcloud.com/playlists" \
-H "accept: application/json; charset=utf-8" \
-H "Content-Type: application/json" \
-H "Authorization: OAuth ACCESS_TOKEN" \
-d '{"playlist": {"title":"YOUR_TITLE", "description":"YOUR_DESCRIPTION", "sharing":"public", "tracks":[{"id":1},{"id":2},{"id":3}]}}'
Adding Tracks to a Playlist
Add tracks to an existing playlist by updating the tracks property via PUT.
curl -X PUT "https://api.soundcloud.com/playlists/PLAYLIST_ID" \
-H "accept: application/json; charset=utf-8" \
-H "Content-Type: application/json" \
-H "Authorization: OAuth ACCESS_TOKEN" \
-d '{"playlist": {"tracks":[{"id":1}, {"id":2}, {"id":3}]}}'
Accessing Playlists
Retrieve tracks in a playlist with a GET request to /playlists/:id.
curl -X GET "https://api.soundcloud.com/playlists/PLAYLIST_ID?show_tracks=false" \
-H "accept: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN"
Playing Tracks
Tracks and playlists can be played from your application by embedding the SoundCloud widget or using stream URLs with a custom audio player. The Widget API provides programmatic control and event handling.
Embedding a SoundCloud Widget
Use the oEmbed endpoint to retrieve embed code for any track or playlist URL.
See also: Embedded player guide, Widget API.
Streaming Tracks
Custom player streaming requires proper attribution per the Terms of Use and Attribution Guidelines:
- Credit the uploader as the creator of the track
- Credit SoundCloud as the source by including one of the logos
- Link to the SoundCloud URL containing the work
- If the track is private, link to the profile of the creator
To stream with a custom player, retrieve the track resource and use its stream_url property. A GET request to the stream URL returns available transcodings.
Public tracks can be streamed without a user session. Private tracks require an authorized user session and a secret_token.
# request a track you want to stream
curl -X GET "https://api.soundcloud.com/tracks/TRACK_ID" \
-H "accept: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN"
# extract stream_url when available from a response
curl -X GET "https://api.soundcloud.com/tracks/TRACK_ID/stream" \
-H "accept: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN"
See also: /oembed, HTML5 Widget API.
Restricted Access
Not all tracks are available for off-platform streaming. Tracks may be restricted by the creator, paywalled, or geo-blocked. Restricted tracks have no stream_url and their access field is set to blocked. Calling /tracks/:id/streams for a blocked track returns an error.
Track access levels:
- playable — the track is fully streamable
- preview — a preview snippet is available
- blocked — not streamable, only metadata is provided
The access filter parameter can be used when searching or fetching tracks to include only tracks with specific access levels. See the API Explorer for details.
Comments
Send a POST request to /tracks/:track_id/comments to create a comment. Include a timestamp parameter (in milliseconds from track start) for a timed comment. Omitting it creates a non-timed comment.
Comments cannot be posted on tracks where the creator has disabled comments.
curl -X POST "https://api.soundcloud.com/tracks/YOUR_TRACK_ID/comments" \
-H "accept: application/json; charset=utf-8" \
-H "Content-Type: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN" \
-d '{"comment":{"body":"YOUR_COMMENT","timestamp":12345}}'
Retrieve comments for a track:
curl -X GET "https://api.soundcloud.com/tracks/YOUR_TRACK_ID/comments?limit=3&linked_partitioning=true" \
-H "accept: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN"
Follow & Like
The API supports following users and liking tracks or playlists. Followed users' tracks and reposts appear in the activity feed.
Follow a user via PUT /me/followings/:user_id:
curl -X PUT "https://api.soundcloud.com/me/followings/USER_ID" \
-H "accept: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN"
Like a track or playlist via the /likes/ endpoints:
# liking a track
curl -X POST "https://api.soundcloud.com/likes/tracks/TRACK_ID" \
-H "accept: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN"
# liking a playlist
curl -X POST "https://api.soundcloud.com/likes/playlists/PLAYLIST_ID" \
-H "accept: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN"
Search
Search tracks, users, and playlists using the q parameter, which matches against fields like title, username, and description.
# search for playable tracks
curl -X GET "https://api.soundcloud.com/tracks?q=hello&ids=1,2,3&genres=Pop,House&access=playable&limit=3&linked_partitioning=true" \
-H "accept: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN"
Range filters are supported for bpm, duration, and other fields:
curl -X GET "https://api.soundcloud.com/tracks?q=hello&ids=1,2,3&genres=Pop,House&bpm%5Bfrom%5D=120&duration%5Bfrom%5D=30000&access=playable&limit=3&linked_partitioning=true" \
-H "accept: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN"
See the API Explorer for all available search fields and filters.
Pagination
Collection responses return up to 50 items by default (maximum 200). Pass linked_partitioning=true to enable pagination. Paginated responses include a next_href property pointing to the next page. When next_href is absent, there are no more results.
# fetch first 25 user's playlists
curl -X GET "https://api.soundcloud.com/me/playlists?show_tracks=false&linked_partitioning=true&limit=25" \
-H "accept: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN"
# response contains 'next_href': "https://api.soundcloud.com/playlists?show_tracks=false&page_size=25&cursor=1234567"
SoundCloud URLs
The /resolve endpoint converts a SoundCloud permalink URL into a full API resource representation.
curl -X GET "https://api.soundcloud.com/resolve?url=https://soundcloud.com/PERMALINK" \
-H "accept: */*" \
-H "Authorization: OAuth ACCESS_TOKEN"
Cross Domain Requests
The API supports CORS for browser-based JavaScript requests. JSONP is also supported via a callback query parameter.
const response = await fetch("https://api.soundcloud.com/tracks?ids=1,2,3", {
headers: {
"Accept": "application/json; charset=utf-8",
"Authorization": "OAuth ACCESS_TOKEN"
}
});
const tracks = await response.json();
tracks.forEach(track => console.log(track.title));
Errors
The API returns standard HTTP status codes with JSON error descriptions.
# try fetching a non-existing user
curl -X GET "https://api.soundcloud.com/users/INVALID_ID" \
-H "accept: application/json; charset=utf-8" \
-H "Authorization: OAuth ACCESS_TOKEN"
# response 404 Error: Not Found
{
"code": 404,
"message": "404 - Not Found",
"link": "https://developers.soundcloud.com/docs/api/explorer/open-api",
"status": "404 - Not Found",
"errors": [
{
"error_message": "404 - Not Found"
}
],
"error": null
}
HTTP Status Codes
400 Bad Request
The request was malformed or missing required parameters. Consult the API Explorer for endpoint requirements.
401 Unauthorized
Authentication failed. Verify the Authorization header is present and contains a valid token.
Public endpoints accept tokens from the Client Credentials flow. User-specific actions require an Authorization Code token. See the Authentication section.
OAuth tokens expire and must be refreshed to avoid 401 errors.
403 Forbidden
The authenticated user does not have permission to access this resource.
404 Not Found
The requested resource does not exist. Verify the URL path and resource ID.
406 Not Accessible
The server cannot produce a response matching the request's Accept header.
422 Unprocessable Entity
One or more parameters failed validation (e.g., wrong data type such as an array where a string was expected).
429 Too Many Requests
The request exceeded a rate limit. See the Rate Limits page for details.
500 Internal Server Error
An unexpected server error occurred.
503 Service Unavailable
The service is temporarily unavailable. Implement retry logic with backoff.
504 Gateway Timeout
The server did not receive a timely upstream response. The request may still have been processed; verify resource state before retrying.