soundcloud

soundcloud.py

Tests Coverage Status Supported Python Versions Version License Monthly Downloads

Python wrapper for some of the internal v2 SoundCloud API (read/GET only methods). Does not require an API key.

Note: This is NOT the official SoundCloud developer API

SoundCloud is not accepting any more application registration requests 1 so I made this library so developers can use SoundCloud's internal API for their projects.

Installation

pip install soundcloud-v2

Documentation

https://7x11x13.xyz/soundcloud.py

Example

from soundcloud import SoundCloud

sc = SoundCloud(auth_token="auth_token")
assert sc.is_client_id_valid()
assert sc.is_auth_token_valid()
me = sc.get_user_by_username("7x11x13")
assert me.permalink == "7x11x13"

Notes on auth_token

Some methods require authentication in the form of an OAuth2 access token. You can find your token in your browser cookies for SoundCloud under the name "oauth_token". A new token will be generated each time you log out and log back in.

Notes on **kwargs

All API methods have a **kwargs argument which you can use to pass extra, undocumented arguments to the SoundCloud v2 API in case I missed some parameter which you find useful. If this is the case, feel free to create an issue or pull request to document the missing argument.

License

MIT

 1# ruff: noqa
 2"""
 3# soundcloud.py
 4
 5[![Tests](https://github.com/7x11x13/soundcloud.py/actions/workflows/ci.yml/badge.svg)](https://github.com/7x11x13/soundcloud.py/actions/workflows/ci.yml)
 6[![Coverage Status](https://coveralls.io/repos/github/7x11x13/soundcloud.py/badge.svg?branch=main)](https://coveralls.io/github/7x11x13/soundcloud.py?branch=main)
 7[![Supported Python Versions](https://img.shields.io/badge/python-3.7%2C%203.8%2C%203.9%2C%203.10%2C%203.11%2C%203.12-blue.svg)](https://pypi.org/project/soundcloud-v2/)
 8[![Version](https://img.shields.io/pypi/v/soundcloud-v2.svg)](https://pypi.org/project/soundcloud-v2/)
 9[![License](https://img.shields.io/pypi/l/soundcloud-v2.svg)](https://pypi.org/project/soundcloud-v2/)
10[![Monthly Downloads](https://pepy.tech/badge/soundcloud-v2/month)](https://pepy.tech/project/soundcloud-v2)
11
12Python wrapper for some of the internal v2 SoundCloud API (read/GET only methods). Does not require an API key.
13
14### Note: This is NOT the official [SoundCloud developer API](https://developers.soundcloud.com/docs/api/guide)
15
16SoundCloud is not accepting any more application registration requests [^1] so
17I made this library so developers can use SoundCloud's internal API for their projects.
18
19
20[^1]: https://docs.google.com/forms/d/e/1FAIpQLSfNxc82RJuzC0DnISat7n4H-G7IsPQIdaMpe202iiHZEoso9w/closedform
21
22## Installation
23
24```bash
25pip install soundcloud-v2
26```
27
28## Documentation
29
30https://7x11x13.xyz/soundcloud.py
31
32## Example
33
34```python
35from soundcloud import SoundCloud
36
37sc = SoundCloud(auth_token="auth_token")
38assert sc.is_client_id_valid()
39assert sc.is_auth_token_valid()
40me = sc.get_user_by_username("7x11x13")
41assert me.permalink == "7x11x13"
42```
43
44## Notes on `auth_token`
45Some methods require authentication in the form of an OAuth2 access token.
46You can find your token in your browser cookies for SoundCloud under the name "oauth_token".
47A new token will be generated each time you log out and log back in.
48
49## Notes on `**kwargs`
50All API methods have a `**kwargs` argument which you can use to pass extra, undocumented
51arguments to the SoundCloud v2 API in case I missed some parameter which you find useful.
52If this is the case, feel free to create an issue or pull request to document the missing
53argument.
54
55## License
56[MIT](https://choosealicense.com/licenses/mit/)
57
58"""
59
60from soundcloud.exceptions import *
61from soundcloud.exceptions import __all__ as ex_all
62from soundcloud.resource import *
63from soundcloud.resource import __all__ as res_all
64from soundcloud.soundcloud import *
65from soundcloud.soundcloud import __all__ as sc_all
66
67__version__ = "1.6.2"
68
69__all__ = sc_all + ex_all + res_all
class SoundCloud:
 76class SoundCloud:
 77    """
 78    SoundCloud v2 API client
 79    """
 80
 81    _DEFAULT_USER_AGENT = (
 82        "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0"
 83    )
 84    _ASSETS_SCRIPTS_REGEX = re.compile(
 85        r"src=\"(https:\/\/a-v2\.sndcdn\.com/assets/.*\.js)\""
 86    )
 87    _CLIENT_ID_REGEX = re.compile(r"client_id:\"([^\"]+)\"")
 88    client_id: str
 89    """SoundCloud client ID. Needed for all requests."""
 90    _user_agent: str
 91    _auth_token: Optional[str]
 92    _authorization: Optional[str]
 93
 94    def __init__(
 95        self,
 96        client_id: Optional[str] = None,
 97        auth_token: Optional[str] = None,
 98        user_agent: str = _DEFAULT_USER_AGENT,
 99    ) -> None:
100        if not client_id:
101            client_id = self.generate_client_id()
102
103        self.client_id = client_id
104        self._user_agent = user_agent
105        self._auth_token = None
106        self._authorization = None
107        self.auth_token = auth_token
108
109    @property
110    def auth_token(self) -> Optional[str]:
111        """SoundCloud auth token. Only needed for some requests."""
112        return self._auth_token
113
114    @auth_token.setter
115    def auth_token(self, new_auth_token: Optional[str]) -> None:
116        if new_auth_token is not None:
117            if new_auth_token.startswith("OAuth"):
118                new_auth_token = new_auth_token.split()[-1]
119        self._authorization = f"OAuth {new_auth_token}" if new_auth_token else None
120        self._auth_token = new_auth_token
121
122    @auth_token.deleter
123    def auth_token(self):
124        self.auth_token = None
125
126    def _get_default_headers(self) -> Dict[str, str]:
127        return {"User-Agent": self._user_agent}
128
129    @classmethod
130    def generate_client_id(cls) -> str:
131        """Generates a SoundCloud client ID
132
133        Raises:
134            ClientIDGenerationError: Client ID could not be generated.
135
136        Returns:
137            str: Valid client ID
138        """
139        r = requests.get("https://soundcloud.com")
140        r.raise_for_status()
141        matches = cls._ASSETS_SCRIPTS_REGEX.findall(r.text)
142        if not matches:
143            raise ClientIDGenerationError("No asset scripts found")
144        for url in matches:
145            r = requests.get(url)
146            r.raise_for_status()
147            client_id = cls._CLIENT_ID_REGEX.search(r.text)
148            if client_id:
149                return client_id.group(1)
150        raise ClientIDGenerationError(f"Could not find client_id in script '{url}'")
151
152    def is_client_id_valid(self) -> bool:
153        """
154        Checks if current client_id is valid
155        """
156        try:
157            TrackRequest(self, track_id=1032303631, use_auth=False)
158            return True
159        except HTTPError as err:
160            if err.response.status_code == 401:
161                return False
162            else:
163                raise
164
165    def is_auth_token_valid(self) -> bool:
166        """
167        Checks if current auth_token is valid
168        """
169        try:
170            MeRequest(self)
171            return True
172        except HTTPError as err:
173            if err.response.status_code == 401:
174                return False
175            else:
176                raise
177
178    def get_me(self) -> Optional[User]:
179        """
180        Gets the user associated with client's auth token
181        """
182        return MeRequest(self)
183
184    def get_my_history(self, **kwargs) -> Generator[HistoryItem, None, None]:
185        """
186        Returns the stream of recently listened tracks
187        for the client's auth token
188        """
189        return MeHistoryRequest(self, **kwargs)
190
191    def get_my_stream(self, **kwargs) -> Generator[StreamItem, None, None]:
192        """
193        Returns the stream of recent uploads/reposts
194        for the client's auth token
195        """
196        return MeStreamRequest(self, **kwargs)
197
198    def resolve(self, url: str) -> Optional[SearchItem]:
199        """
200        Returns the resource at the given URL if it
201        exists, otherwise return None
202        """
203        return ResolveRequest(self, url=url)
204
205    def search(self, query: str, **kwargs) -> Generator[SearchItem, None, None]:
206        """
207        Search for users, tracks, and playlists
208        """
209        return SearchRequest(self, q=query, **kwargs)
210
211    def search_albums(
212        self, query: str, **kwargs
213    ) -> Generator[AlbumPlaylist, None, None]:
214        """
215        Search for albums (not playlists)
216        """
217        return SearchAlbumsRequest(self, q=query, **kwargs)
218
219    def search_playlists(
220        self, query: str, **kwargs
221    ) -> Generator[AlbumPlaylist, None, None]:
222        """
223        Search for playlists
224        """
225        return SearchPlaylistsRequest(self, q=query, **kwargs)
226
227    def search_tracks(self, query: str, **kwargs) -> Generator[Track, None, None]:
228        """
229        Search for tracks
230        """
231        return SearchTracksRequest(self, q=query, **kwargs)
232
233    def search_users(self, query: str, **kwargs) -> Generator[User, None, None]:
234        """
235        Search for users
236        """
237        return SearchUsersRequest(self, q=query, **kwargs)
238
239    def get_tag_tracks_recent(self, tag: str, **kwargs) -> Generator[Track, None, None]:
240        """
241        Get most recent tracks for this tag
242        """
243        return TagRecentTracksRequest(self, tag=tag, **kwargs)
244
245    def get_playlist(self, playlist_id: int) -> Optional[BasicAlbumPlaylist]:
246        """
247        Returns the playlist with the given playlist_id.
248        If the ID is invalid, return None
249        """
250        return PlaylistRequest(self, playlist_id=playlist_id)
251
252    def post_playlist(
253        self, sharing: Literal["private", "public"], title: str, tracks: List[int]
254    ) -> Optional[BasicAlbumPlaylist]:
255        """
256        Create a new playlist
257        """
258        body = {"playlist": {"sharing": sharing, "title": title, "tracks": tracks}}
259        return PostPlaylistRequest(self, body=body)
260
261    def delete_playlist(self, playlist_id: int) -> Optional[NoContentResponse]:
262        """
263        Delete a playlist
264        """
265        return DeletePlaylistRequest(self, playlist_id=playlist_id)
266
267    def get_playlist_likers(
268        self, playlist_id: int, **kwargs
269    ) -> Generator[User, None, None]:
270        """
271        Get people who liked this playlist
272        """
273        return PlaylistLikersRequest(self, playlist_id=playlist_id, **kwargs)
274
275    def get_playlist_reposters(
276        self, playlist_id: int, **kwargs
277    ) -> Generator[User, None, None]:
278        """
279        Get people who reposted this playlist
280        """
281        return PlaylistRepostersRequest(self, playlist_id=playlist_id, **kwargs)
282
283    def get_track(self, track_id: int) -> Optional[BasicTrack]:
284        """
285        Returns the track with the given track_id.
286        If the ID is invalid, return None
287        """
288        return TrackRequest(self, track_id=track_id)
289
290    def get_tracks(
291        self,
292        track_ids: List[int],
293        playlistId: Optional[int] = None,
294        playlistSecretToken: Optional[str] = None,
295        **kwargs,
296    ) -> List[BasicTrack]:
297        """
298        Returns the tracks with the given track_ids.
299        Can be used to get track info for hidden tracks in a hidden playlist.
300        """
301        if playlistId is not None:
302            kwargs["playlistId"] = playlistId
303        if playlistSecretToken is not None:
304            kwargs["playlistSecretToken"] = playlistSecretToken
305        return TracksRequest(
306            self, ids=",".join([str(id) for id in track_ids]), **kwargs
307        )
308
309    def get_track_albums(
310        self, track_id: int, **kwargs
311    ) -> Generator[BasicAlbumPlaylist, None, None]:
312        """
313        Get albums that this track is in
314        """
315        return TrackAlbumsRequest(self, track_id=track_id, **kwargs)
316
317    def get_track_playlists(
318        self, track_id: int, **kwargs
319    ) -> Generator[BasicAlbumPlaylist, None, None]:
320        """
321        Get playlists that this track is in
322        """
323        return TrackPlaylistsRequest(self, track_id=track_id, **kwargs)
324
325    def get_track_comments(
326        self, track_id: int, threaded: int = 0, **kwargs
327    ) -> Generator[BasicComment, None, None]:
328        """
329        Get comments on this track
330        """
331        return TrackCommentsRequest(
332            self, track_id=track_id, threaded=threaded, **kwargs
333        )
334
335    def get_track_comments_with_interactions(
336        self, track_id: int, threaded: int = 0, **kwargs
337    ) -> Generator[CommentWithInteractions, None, None]:
338        """
339        Get comments on this track with interaction data. Requires authentication.
340        """
341        track = self.get_track(track_id)
342        if not track:
343            return
344        track_urn = track.urn
345        creator_urn = track.user.urn
346        comments = self.get_track_comments(track_id, threaded, **kwargs)
347        while True:
348            chunk = list(itertools.islice(comments, 10))
349            if not chunk:
350                return
351            comment_urns = [comment.self.urn for comment in chunk]
352            result = UserInteractionsRequest(
353                self,
354                UserInteractionsQueryParams(
355                    creator_urn,
356                    "sc:interactiontype:reaction",
357                    track_urn,
358                    comment_urns,
359                ),
360            )
361            if not result:
362                return
363            comments_with_interactions = []
364            for comment, user_interactions, creator_interactions in zip(
365                chunk, result.user, result.creator
366            ):
367                assert user_interactions.interactionCounts is not None
368                likes = list(
369                    filter(
370                        lambda x: x.interactionTypeValueUrn
371                        == "sc:interactiontypevalue:like",
372                        user_interactions.interactionCounts,
373                    )
374                )
375                num_likes = likes[0].count if likes else 0
376                comments_with_interactions.append(
377                    CommentWithInteractions(
378                        comment=comment,
379                        likes=num_likes or 0,
380                        liked_by_creator=creator_interactions.userInteraction
381                        == "sc:interactiontypevalue:like",
382                        liked_by_user=user_interactions.userInteraction
383                        == "sc:interactiontypevalue:like",
384                    )
385                )
386            yield from comments_with_interactions
387
388    def get_track_likers(self, track_id: int, **kwargs) -> Generator[User, None, None]:
389        """
390        Get users who liked this track
391        """
392        return TrackLikersRequest(self, track_id=track_id, **kwargs)
393
394    def get_track_related(
395        self, track_id: int, **kwargs
396    ) -> Generator[BasicTrack, None, None]:
397        """
398        Get related tracks
399        """
400        return TrackRelatedRequest(self, track_id=track_id, **kwargs)
401
402    def get_track_reposters(
403        self, track_id: int, **kwargs
404    ) -> Generator[User, None, None]:
405        """
406        Get users who reposted this track
407        """
408        return TrackRepostersRequest(self, track_id=track_id, **kwargs)
409
410    def get_track_original_download(
411        self, track_id: int, token: Optional[str] = None
412    ) -> Optional[str]:
413        """
414        Get track original download link. If track is private,
415        requires secret token to be provided (last part of secret URL).
416        Requires authentication.
417        """
418        if token is not None:
419            download = TrackOriginalDownloadRequest(
420                self, track_id=track_id, secret_token=token
421            )
422        else:
423            download = TrackOriginalDownloadRequest(self, track_id=track_id)
424        if download is None:
425            return None
426        else:
427            return download.redirectUri
428
429    def get_user(self, user_id: int) -> Optional[User]:
430        """
431        Returns the user with the given user_id.
432        If the ID is invalid, return None
433        """
434        return UserRequest(self, user_id=user_id)
435
436    def get_user_by_username(self, username: str) -> Optional[User]:
437        """
438        Returns the user with the given username.
439        If the username is invalid, return None
440        """
441        resource = self.resolve(f"https://soundcloud.com/{username}")
442        if resource and isinstance(resource, User):
443            return resource
444        else:
445            return None
446
447    def get_user_comments(
448        self, user_id: int, **kwargs
449    ) -> Generator[Comment, None, None]:
450        """
451        Get comments by this user
452        """
453        return UserCommentsRequest(self, user_id=user_id, **kwargs)
454
455    def get_conversation_messages(
456        self, user_id: int, conversation_id: int, **kwargs
457    ) -> Generator[Message, None, None]:
458        """
459        Get messages in this conversation
460        """
461        return UserConversationMessagesRequest(
462            self, user_id=user_id, conversation_id=conversation_id, **kwargs
463        )
464
465    def get_conversations(
466        self, user_id: int, **kwargs
467    ) -> Generator[Conversation, None, None]:
468        """
469        Get conversations including this user
470        """
471        return UserConversationsRequest(self, user_id=user_id, **kwargs)
472
473    def get_unread_conversations(
474        self, user_id: int, **kwargs
475    ) -> Generator[Conversation, None, None]:
476        """
477        Get conversations unread by this user
478        """
479        return UserConversationsUnreadRequest(self, user_id=user_id, **kwargs)
480
481    def get_user_emails(
482        self, user_id: int, **kwargs
483    ) -> Generator[UserEmail, None, None]:
484        """
485        Get user's email addresses. Requires authentication.
486        """
487        return UserEmailsRequest(self, user_id=user_id, **kwargs)
488
489    def get_user_featured_profiles(
490        self, user_id: int, **kwargs
491    ) -> Generator[User, None, None]:
492        """
493        Get profiles featured by this user
494        """
495        return UserFeaturedProfilesRequest(self, user_id=user_id, **kwargs)
496
497    def get_user_followers(self, user_id: int, **kwargs) -> Generator[User, None, None]:
498        """
499        Get user's followers
500        """
501        return UserFollowersRequest(self, user_id=user_id, **kwargs)
502
503    def get_user_following(self, user_id: int, **kwargs) -> Generator[User, None, None]:
504        """
505        Get users this user is following
506        """
507        return UserFollowingsRequest(self, user_id=user_id, **kwargs)
508
509    def get_user_likes(self, user_id: int, **kwargs) -> Generator[Like, None, None]:
510        """
511        Get likes by this user
512        """
513        return UserLikesRequest(self, user_id=user_id, **kwargs)
514
515    def get_user_related_artists(
516        self, user_id: int, **kwargs
517    ) -> Generator[User, None, None]:
518        """
519        Get artists related to this user
520        """
521        return UserRelatedArtistsRequest(self, user_id=user_id, **kwargs)
522
523    def get_user_reposts(
524        self, user_id: int, **kwargs
525    ) -> Generator[RepostItem, None, None]:
526        """
527        Get reposts by this user
528        """
529        return UserRepostsRequest(self, user_id=user_id, **kwargs)
530
531    def get_user_stream(
532        self, user_id: int, **kwargs
533    ) -> Generator[StreamItem, None, None]:
534        """
535        Returns generator of track uploaded by given user and
536        reposts by this user
537        """
538        return UserStreamRequest(self, user_id=user_id, **kwargs)
539
540    def get_user_tracks(
541        self, user_id: int, **kwargs
542    ) -> Generator[BasicTrack, None, None]:
543        """
544        Get tracks uploaded by this user
545        """
546        return UserTracksRequest(self, user_id=user_id, **kwargs)
547
548    def get_user_popular_tracks(
549        self, user_id: int, **kwargs
550    ) -> Generator[BasicTrack, None, None]:
551        """
552        Get popular tracks uploaded by this user
553        """
554        return UserToptracksRequest(self, user_id=user_id, **kwargs)
555
556    def get_user_albums(
557        self, user_id: int, **kwargs
558    ) -> Generator[BasicAlbumPlaylist, None, None]:
559        """
560        Get albums uploaded by this user
561        """
562        return UserAlbumsRequest(self, user_id=user_id, **kwargs)
563
564    def get_user_playlists(
565        self, user_id: int, **kwargs
566    ) -> Generator[BasicAlbumPlaylist, None, None]:
567        """
568        Get playlists uploaded by this user
569        """
570        return UserPlaylistsRequest(self, user_id=user_id, **kwargs)
571
572    def get_user_links(self, user_urn: str, **kwargs) -> List[WebProfile]:
573        """
574        Get links in this user's description
575        """
576        return UserWebProfilesRequest(self, user_urn=user_urn, **kwargs)

SoundCloud v2 API client

SoundCloud( client_id: Optional[str] = None, auth_token: Optional[str] = None, user_agent: str = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0')
 94    def __init__(
 95        self,
 96        client_id: Optional[str] = None,
 97        auth_token: Optional[str] = None,
 98        user_agent: str = _DEFAULT_USER_AGENT,
 99    ) -> None:
100        if not client_id:
101            client_id = self.generate_client_id()
102
103        self.client_id = client_id
104        self._user_agent = user_agent
105        self._auth_token = None
106        self._authorization = None
107        self.auth_token = auth_token
client_id: str

SoundCloud client ID. Needed for all requests.

auth_token: Optional[str]
109    @property
110    def auth_token(self) -> Optional[str]:
111        """SoundCloud auth token. Only needed for some requests."""
112        return self._auth_token

SoundCloud auth token. Only needed for some requests.

@classmethod
def generate_client_id(cls) -> str:
129    @classmethod
130    def generate_client_id(cls) -> str:
131        """Generates a SoundCloud client ID
132
133        Raises:
134            ClientIDGenerationError: Client ID could not be generated.
135
136        Returns:
137            str: Valid client ID
138        """
139        r = requests.get("https://soundcloud.com")
140        r.raise_for_status()
141        matches = cls._ASSETS_SCRIPTS_REGEX.findall(r.text)
142        if not matches:
143            raise ClientIDGenerationError("No asset scripts found")
144        for url in matches:
145            r = requests.get(url)
146            r.raise_for_status()
147            client_id = cls._CLIENT_ID_REGEX.search(r.text)
148            if client_id:
149                return client_id.group(1)
150        raise ClientIDGenerationError(f"Could not find client_id in script '{url}'")

Generates a SoundCloud client ID

Raises:
  • ClientIDGenerationError: Client ID could not be generated.
Returns:

str: Valid client ID

def is_client_id_valid(self) -> bool:
152    def is_client_id_valid(self) -> bool:
153        """
154        Checks if current client_id is valid
155        """
156        try:
157            TrackRequest(self, track_id=1032303631, use_auth=False)
158            return True
159        except HTTPError as err:
160            if err.response.status_code == 401:
161                return False
162            else:
163                raise

Checks if current client_id is valid

def is_auth_token_valid(self) -> bool:
165    def is_auth_token_valid(self) -> bool:
166        """
167        Checks if current auth_token is valid
168        """
169        try:
170            MeRequest(self)
171            return True
172        except HTTPError as err:
173            if err.response.status_code == 401:
174                return False
175            else:
176                raise

Checks if current auth_token is valid

def get_me(self) -> Optional[User]:
178    def get_me(self) -> Optional[User]:
179        """
180        Gets the user associated with client's auth token
181        """
182        return MeRequest(self)

Gets the user associated with client's auth token

def get_my_history( self, **kwargs) -> Generator[HistoryItem, NoneType, NoneType]:
184    def get_my_history(self, **kwargs) -> Generator[HistoryItem, None, None]:
185        """
186        Returns the stream of recently listened tracks
187        for the client's auth token
188        """
189        return MeHistoryRequest(self, **kwargs)

Returns the stream of recently listened tracks for the client's auth token

def get_my_stream( self, **kwargs) -> Generator[Union[TrackStreamItem, PlaylistStreamItem, TrackStreamRepostItem, PlaylistStreamRepostItem], NoneType, NoneType]:
191    def get_my_stream(self, **kwargs) -> Generator[StreamItem, None, None]:
192        """
193        Returns the stream of recent uploads/reposts
194        for the client's auth token
195        """
196        return MeStreamRequest(self, **kwargs)

Returns the stream of recent uploads/reposts for the client's auth token

def resolve( self, url: str) -> Union[User, Track, AlbumPlaylist, NoneType]:
198    def resolve(self, url: str) -> Optional[SearchItem]:
199        """
200        Returns the resource at the given URL if it
201        exists, otherwise return None
202        """
203        return ResolveRequest(self, url=url)

Returns the resource at the given URL if it exists, otherwise return None

def search( self, query: str, **kwargs) -> Generator[Union[User, Track, AlbumPlaylist], NoneType, NoneType]:
205    def search(self, query: str, **kwargs) -> Generator[SearchItem, None, None]:
206        """
207        Search for users, tracks, and playlists
208        """
209        return SearchRequest(self, q=query, **kwargs)

Search for users, tracks, and playlists

def search_albums( self, query: str, **kwargs) -> Generator[AlbumPlaylist, NoneType, NoneType]:
211    def search_albums(
212        self, query: str, **kwargs
213    ) -> Generator[AlbumPlaylist, None, None]:
214        """
215        Search for albums (not playlists)
216        """
217        return SearchAlbumsRequest(self, q=query, **kwargs)

Search for albums (not playlists)

def search_playlists( self, query: str, **kwargs) -> Generator[AlbumPlaylist, NoneType, NoneType]:
219    def search_playlists(
220        self, query: str, **kwargs
221    ) -> Generator[AlbumPlaylist, None, None]:
222        """
223        Search for playlists
224        """
225        return SearchPlaylistsRequest(self, q=query, **kwargs)

Search for playlists

def search_tracks( self, query: str, **kwargs) -> Generator[Track, NoneType, NoneType]:
227    def search_tracks(self, query: str, **kwargs) -> Generator[Track, None, None]:
228        """
229        Search for tracks
230        """
231        return SearchTracksRequest(self, q=query, **kwargs)

Search for tracks

def search_users( self, query: str, **kwargs) -> Generator[User, NoneType, NoneType]:
233    def search_users(self, query: str, **kwargs) -> Generator[User, None, None]:
234        """
235        Search for users
236        """
237        return SearchUsersRequest(self, q=query, **kwargs)

Search for users

def get_tag_tracks_recent( self, tag: str, **kwargs) -> Generator[Track, NoneType, NoneType]:
239    def get_tag_tracks_recent(self, tag: str, **kwargs) -> Generator[Track, None, None]:
240        """
241        Get most recent tracks for this tag
242        """
243        return TagRecentTracksRequest(self, tag=tag, **kwargs)

Get most recent tracks for this tag

def get_playlist( self, playlist_id: int) -> Optional[BasicAlbumPlaylist]:
245    def get_playlist(self, playlist_id: int) -> Optional[BasicAlbumPlaylist]:
246        """
247        Returns the playlist with the given playlist_id.
248        If the ID is invalid, return None
249        """
250        return PlaylistRequest(self, playlist_id=playlist_id)

Returns the playlist with the given playlist_id. If the ID is invalid, return None

def post_playlist( self, sharing: Literal['private', 'public'], title: str, tracks: List[int]) -> Optional[BasicAlbumPlaylist]:
252    def post_playlist(
253        self, sharing: Literal["private", "public"], title: str, tracks: List[int]
254    ) -> Optional[BasicAlbumPlaylist]:
255        """
256        Create a new playlist
257        """
258        body = {"playlist": {"sharing": sharing, "title": title, "tracks": tracks}}
259        return PostPlaylistRequest(self, body=body)

Create a new playlist

def delete_playlist( self, playlist_id: int) -> Optional[NoContentResponse]:
261    def delete_playlist(self, playlist_id: int) -> Optional[NoContentResponse]:
262        """
263        Delete a playlist
264        """
265        return DeletePlaylistRequest(self, playlist_id=playlist_id)

Delete a playlist

def get_playlist_likers( self, playlist_id: int, **kwargs) -> Generator[User, NoneType, NoneType]:
267    def get_playlist_likers(
268        self, playlist_id: int, **kwargs
269    ) -> Generator[User, None, None]:
270        """
271        Get people who liked this playlist
272        """
273        return PlaylistLikersRequest(self, playlist_id=playlist_id, **kwargs)

Get people who liked this playlist

def get_playlist_reposters( self, playlist_id: int, **kwargs) -> Generator[User, NoneType, NoneType]:
275    def get_playlist_reposters(
276        self, playlist_id: int, **kwargs
277    ) -> Generator[User, None, None]:
278        """
279        Get people who reposted this playlist
280        """
281        return PlaylistRepostersRequest(self, playlist_id=playlist_id, **kwargs)

Get people who reposted this playlist

def get_track(self, track_id: int) -> Optional[BasicTrack]:
283    def get_track(self, track_id: int) -> Optional[BasicTrack]:
284        """
285        Returns the track with the given track_id.
286        If the ID is invalid, return None
287        """
288        return TrackRequest(self, track_id=track_id)

Returns the track with the given track_id. If the ID is invalid, return None

def get_tracks( self, track_ids: List[int], playlistId: Optional[int] = None, playlistSecretToken: Optional[str] = None, **kwargs) -> List[BasicTrack]:
290    def get_tracks(
291        self,
292        track_ids: List[int],
293        playlistId: Optional[int] = None,
294        playlistSecretToken: Optional[str] = None,
295        **kwargs,
296    ) -> List[BasicTrack]:
297        """
298        Returns the tracks with the given track_ids.
299        Can be used to get track info for hidden tracks in a hidden playlist.
300        """
301        if playlistId is not None:
302            kwargs["playlistId"] = playlistId
303        if playlistSecretToken is not None:
304            kwargs["playlistSecretToken"] = playlistSecretToken
305        return TracksRequest(
306            self, ids=",".join([str(id) for id in track_ids]), **kwargs
307        )

Returns the tracks with the given track_ids. Can be used to get track info for hidden tracks in a hidden playlist.

def get_track_albums( self, track_id: int, **kwargs) -> Generator[BasicAlbumPlaylist, NoneType, NoneType]:
309    def get_track_albums(
310        self, track_id: int, **kwargs
311    ) -> Generator[BasicAlbumPlaylist, None, None]:
312        """
313        Get albums that this track is in
314        """
315        return TrackAlbumsRequest(self, track_id=track_id, **kwargs)

Get albums that this track is in

def get_track_playlists( self, track_id: int, **kwargs) -> Generator[BasicAlbumPlaylist, NoneType, NoneType]:
317    def get_track_playlists(
318        self, track_id: int, **kwargs
319    ) -> Generator[BasicAlbumPlaylist, None, None]:
320        """
321        Get playlists that this track is in
322        """
323        return TrackPlaylistsRequest(self, track_id=track_id, **kwargs)

Get playlists that this track is in

def get_track_comments( self, track_id: int, threaded: int = 0, **kwargs) -> Generator[BasicComment, NoneType, NoneType]:
325    def get_track_comments(
326        self, track_id: int, threaded: int = 0, **kwargs
327    ) -> Generator[BasicComment, None, None]:
328        """
329        Get comments on this track
330        """
331        return TrackCommentsRequest(
332            self, track_id=track_id, threaded=threaded, **kwargs
333        )

Get comments on this track

def get_track_comments_with_interactions( self, track_id: int, threaded: int = 0, **kwargs) -> Generator[CommentWithInteractions, NoneType, NoneType]:
335    def get_track_comments_with_interactions(
336        self, track_id: int, threaded: int = 0, **kwargs
337    ) -> Generator[CommentWithInteractions, None, None]:
338        """
339        Get comments on this track with interaction data. Requires authentication.
340        """
341        track = self.get_track(track_id)
342        if not track:
343            return
344        track_urn = track.urn
345        creator_urn = track.user.urn
346        comments = self.get_track_comments(track_id, threaded, **kwargs)
347        while True:
348            chunk = list(itertools.islice(comments, 10))
349            if not chunk:
350                return
351            comment_urns = [comment.self.urn for comment in chunk]
352            result = UserInteractionsRequest(
353                self,
354                UserInteractionsQueryParams(
355                    creator_urn,
356                    "sc:interactiontype:reaction",
357                    track_urn,
358                    comment_urns,
359                ),
360            )
361            if not result:
362                return
363            comments_with_interactions = []
364            for comment, user_interactions, creator_interactions in zip(
365                chunk, result.user, result.creator
366            ):
367                assert user_interactions.interactionCounts is not None
368                likes = list(
369                    filter(
370                        lambda x: x.interactionTypeValueUrn
371                        == "sc:interactiontypevalue:like",
372                        user_interactions.interactionCounts,
373                    )
374                )
375                num_likes = likes[0].count if likes else 0
376                comments_with_interactions.append(
377                    CommentWithInteractions(
378                        comment=comment,
379                        likes=num_likes or 0,
380                        liked_by_creator=creator_interactions.userInteraction
381                        == "sc:interactiontypevalue:like",
382                        liked_by_user=user_interactions.userInteraction
383                        == "sc:interactiontypevalue:like",
384                    )
385                )
386            yield from comments_with_interactions

Get comments on this track with interaction data. Requires authentication.

def get_track_likers( self, track_id: int, **kwargs) -> Generator[User, NoneType, NoneType]:
388    def get_track_likers(self, track_id: int, **kwargs) -> Generator[User, None, None]:
389        """
390        Get users who liked this track
391        """
392        return TrackLikersRequest(self, track_id=track_id, **kwargs)

Get users who liked this track

def get_track_reposters( self, track_id: int, **kwargs) -> Generator[User, NoneType, NoneType]:
402    def get_track_reposters(
403        self, track_id: int, **kwargs
404    ) -> Generator[User, None, None]:
405        """
406        Get users who reposted this track
407        """
408        return TrackRepostersRequest(self, track_id=track_id, **kwargs)

Get users who reposted this track

def get_track_original_download(self, track_id: int, token: Optional[str] = None) -> Optional[str]:
410    def get_track_original_download(
411        self, track_id: int, token: Optional[str] = None
412    ) -> Optional[str]:
413        """
414        Get track original download link. If track is private,
415        requires secret token to be provided (last part of secret URL).
416        Requires authentication.
417        """
418        if token is not None:
419            download = TrackOriginalDownloadRequest(
420                self, track_id=track_id, secret_token=token
421            )
422        else:
423            download = TrackOriginalDownloadRequest(self, track_id=track_id)
424        if download is None:
425            return None
426        else:
427            return download.redirectUri

Get track original download link. If track is private, requires secret token to be provided (last part of secret URL). Requires authentication.

def get_user(self, user_id: int) -> Optional[User]:
429    def get_user(self, user_id: int) -> Optional[User]:
430        """
431        Returns the user with the given user_id.
432        If the ID is invalid, return None
433        """
434        return UserRequest(self, user_id=user_id)

Returns the user with the given user_id. If the ID is invalid, return None

def get_user_by_username(self, username: str) -> Optional[User]:
436    def get_user_by_username(self, username: str) -> Optional[User]:
437        """
438        Returns the user with the given username.
439        If the username is invalid, return None
440        """
441        resource = self.resolve(f"https://soundcloud.com/{username}")
442        if resource and isinstance(resource, User):
443            return resource
444        else:
445            return None

Returns the user with the given username. If the username is invalid, return None

def get_user_comments( self, user_id: int, **kwargs) -> Generator[Comment, NoneType, NoneType]:
447    def get_user_comments(
448        self, user_id: int, **kwargs
449    ) -> Generator[Comment, None, None]:
450        """
451        Get comments by this user
452        """
453        return UserCommentsRequest(self, user_id=user_id, **kwargs)

Get comments by this user

def get_conversation_messages( self, user_id: int, conversation_id: int, **kwargs) -> Generator[Message, NoneType, NoneType]:
455    def get_conversation_messages(
456        self, user_id: int, conversation_id: int, **kwargs
457    ) -> Generator[Message, None, None]:
458        """
459        Get messages in this conversation
460        """
461        return UserConversationMessagesRequest(
462            self, user_id=user_id, conversation_id=conversation_id, **kwargs
463        )

Get messages in this conversation

def get_conversations( self, user_id: int, **kwargs) -> Generator[Conversation, NoneType, NoneType]:
465    def get_conversations(
466        self, user_id: int, **kwargs
467    ) -> Generator[Conversation, None, None]:
468        """
469        Get conversations including this user
470        """
471        return UserConversationsRequest(self, user_id=user_id, **kwargs)

Get conversations including this user

def get_unread_conversations( self, user_id: int, **kwargs) -> Generator[Conversation, NoneType, NoneType]:
473    def get_unread_conversations(
474        self, user_id: int, **kwargs
475    ) -> Generator[Conversation, None, None]:
476        """
477        Get conversations unread by this user
478        """
479        return UserConversationsUnreadRequest(self, user_id=user_id, **kwargs)

Get conversations unread by this user

def get_user_emails( self, user_id: int, **kwargs) -> Generator[UserEmail, NoneType, NoneType]:
481    def get_user_emails(
482        self, user_id: int, **kwargs
483    ) -> Generator[UserEmail, None, None]:
484        """
485        Get user's email addresses. Requires authentication.
486        """
487        return UserEmailsRequest(self, user_id=user_id, **kwargs)

Get user's email addresses. Requires authentication.

def get_user_followers( self, user_id: int, **kwargs) -> Generator[User, NoneType, NoneType]:
497    def get_user_followers(self, user_id: int, **kwargs) -> Generator[User, None, None]:
498        """
499        Get user's followers
500        """
501        return UserFollowersRequest(self, user_id=user_id, **kwargs)

Get user's followers

def get_user_following( self, user_id: int, **kwargs) -> Generator[User, NoneType, NoneType]:
503    def get_user_following(self, user_id: int, **kwargs) -> Generator[User, None, None]:
504        """
505        Get users this user is following
506        """
507        return UserFollowingsRequest(self, user_id=user_id, **kwargs)

Get users this user is following

def get_user_likes( self, user_id: int, **kwargs) -> Generator[Union[TrackLike, PlaylistLike], NoneType, NoneType]:
509    def get_user_likes(self, user_id: int, **kwargs) -> Generator[Like, None, None]:
510        """
511        Get likes by this user
512        """
513        return UserLikesRequest(self, user_id=user_id, **kwargs)

Get likes by this user

def get_user_reposts( self, user_id: int, **kwargs) -> Generator[Union[TrackStreamRepostItem, PlaylistStreamRepostItem], NoneType, NoneType]:
523    def get_user_reposts(
524        self, user_id: int, **kwargs
525    ) -> Generator[RepostItem, None, None]:
526        """
527        Get reposts by this user
528        """
529        return UserRepostsRequest(self, user_id=user_id, **kwargs)

Get reposts by this user

def get_user_stream( self, user_id: int, **kwargs) -> Generator[Union[TrackStreamItem, PlaylistStreamItem, TrackStreamRepostItem, PlaylistStreamRepostItem], NoneType, NoneType]:
531    def get_user_stream(
532        self, user_id: int, **kwargs
533    ) -> Generator[StreamItem, None, None]:
534        """
535        Returns generator of track uploaded by given user and
536        reposts by this user
537        """
538        return UserStreamRequest(self, user_id=user_id, **kwargs)

Returns generator of track uploaded by given user and reposts by this user

def get_user_tracks( self, user_id: int, **kwargs) -> Generator[BasicTrack, NoneType, NoneType]:
540    def get_user_tracks(
541        self, user_id: int, **kwargs
542    ) -> Generator[BasicTrack, None, None]:
543        """
544        Get tracks uploaded by this user
545        """
546        return UserTracksRequest(self, user_id=user_id, **kwargs)

Get tracks uploaded by this user

def get_user_albums( self, user_id: int, **kwargs) -> Generator[BasicAlbumPlaylist, NoneType, NoneType]:
556    def get_user_albums(
557        self, user_id: int, **kwargs
558    ) -> Generator[BasicAlbumPlaylist, None, None]:
559        """
560        Get albums uploaded by this user
561        """
562        return UserAlbumsRequest(self, user_id=user_id, **kwargs)

Get albums uploaded by this user

def get_user_playlists( self, user_id: int, **kwargs) -> Generator[BasicAlbumPlaylist, NoneType, NoneType]:
564    def get_user_playlists(
565        self, user_id: int, **kwargs
566    ) -> Generator[BasicAlbumPlaylist, None, None]:
567        """
568        Get playlists uploaded by this user
569        """
570        return UserPlaylistsRequest(self, user_id=user_id, **kwargs)

Get playlists uploaded by this user

class ClientIDGenerationError(builtins.Exception):
2class ClientIDGenerationError(Exception):
3    """
4    Raised when a client ID could not be dynamically generated.
5    """

Raised when a client ID could not be dynamically generated.

Like = typing.Union[TrackLike, PlaylistLike]
RepostItem = typing.Union[TrackStreamRepostItem, PlaylistStreamRepostItem]
SearchItem = typing.Union[User, Track, AlbumPlaylist]
@dataclass
class BasicComment(soundcloud.resource.base.BaseData):
16@dataclass
17class BasicComment(BaseData):
18    """Comment without a specified track"""
19
20    kind: str
21    id: int
22    body: str
23    created_at: datetime.datetime
24    timestamp: Optional[int]
25    track_id: int
26    user_id: int
27    self: CommentSelf
28    user: BasicUser

Comment without a specified track

BasicComment( kind: str, id: int, body: str, created_at: datetime.datetime, timestamp: Optional[int], track_id: int, user_id: int, self: CommentSelf, user: BasicUser)
kind: str
id: int
body: str
created_at: datetime.datetime
timestamp: Optional[int]
track_id: int
user_id: int
self: CommentSelf
user: BasicUser
@dataclass
class Comment(soundcloud.BasicComment):
31@dataclass
32class Comment(BasicComment):
33    """Comment with a specified track"""
34
35    track: CommentTrack

Comment with a specified track

Comment( kind: str, id: int, body: str, created_at: datetime.datetime, timestamp: Optional[int], track_id: int, user_id: int, self: CommentSelf, user: BasicUser, track: CommentTrack)
track: CommentTrack
@dataclass
class CommentWithInteractions(soundcloud.resource.base.BaseData):
25@dataclass
26class CommentWithInteractions(BaseData):
27    comment: BasicComment
28    likes: int
29    """Number of likes on comment"""
30
31    liked_by_creator: bool
32    """Whether comment was liked by the track creator"""
33
34    liked_by_user: bool
35    """Whether the current logged in user liked the comment"""
CommentWithInteractions( comment: BasicComment, likes: int, liked_by_creator: bool, liked_by_user: bool)
comment: BasicComment
likes: int

Number of likes on comment

liked_by_creator: bool

Whether comment was liked by the track creator

liked_by_user: bool

Whether the current logged in user liked the comment

@dataclass
class CommentSelf(soundcloud.resource.base.BaseData):
11@dataclass
12class CommentSelf(BaseData):
13    urn: str
CommentSelf(urn: str)
urn: str
@dataclass
class Conversation(soundcloud.resource.base.BaseData):
11@dataclass
12class Conversation(BaseData):
13    """DM conversation between two users"""
14
15    id: str
16    last_message: Message
17    read: bool
18    started_at: datetime.datetime
19    summary: str
20    users: Tuple[Union[BasicUser, MissingUser], ...]

DM conversation between two users

Conversation( id: str, last_message: Message, read: bool, started_at: datetime.datetime, summary: str, users: Tuple[Union[BasicUser, soundcloud.resource.user.MissingUser], ...])
id: str
last_message: Message
read: bool
started_at: datetime.datetime
summary: str
users: Tuple[Union[BasicUser, soundcloud.resource.user.MissingUser], ...]
@dataclass
class OriginalDownload(soundcloud.resource.base.BaseData):
 7@dataclass
 8class OriginalDownload(BaseData):
 9    """Contains a download link for a track"""
10
11    redirectUri: str

Contains a download link for a track

OriginalDownload(redirectUri: str)
redirectUri: str
@dataclass
class HistoryItem(soundcloud.resource.base.BaseData):
 8@dataclass
 9class HistoryItem(BaseData):
10    """Item in user's listen history"""
11
12    played_at: int
13    track: BasicTrack
14    track_id: int

Item in user's listen history

HistoryItem( played_at: int, track: BasicTrack, track_id: int)
played_at: int
track: BasicTrack
track_id: int
@dataclass
class PlaylistLike(soundcloud.resource.like.BaseLike):
23@dataclass
24class PlaylistLike(BaseLike):
25    """Like on a playlist"""
26
27    playlist: AlbumPlaylistNoTracks

Like on a playlist

PlaylistLike( created_at: datetime.datetime, kind: str, playlist: AlbumPlaylistNoTracks)
@dataclass
class TrackLike(soundcloud.resource.like.BaseLike):
16@dataclass
17class TrackLike(BaseLike):
18    """Like on a track"""
19
20    track: BasicTrack

Like on a track

TrackLike( created_at: datetime.datetime, kind: str, track: BasicTrack)
track: BasicTrack
@dataclass
class Message(soundcloud.resource.base.BaseData):
10@dataclass
11class Message(BaseData):
12    """Single DM between two users"""
13
14    content: str
15    conversation_id: str
16    sender: Union[BasicUser, MissingUser]
17    sender_urn: str
18    sender_type: str
19    sent_at: datetime.datetime

Single DM between two users

Message( content: str, conversation_id: str, sender: Union[BasicUser, soundcloud.resource.user.MissingUser], sender_urn: str, sender_type: str, sent_at: datetime.datetime)
content: str
conversation_id: str
sender: Union[BasicUser, soundcloud.resource.user.MissingUser]
sender_urn: str
sender_type: str
sent_at: datetime.datetime
@dataclass
class AlbumPlaylist(soundcloud.resource.playlist.BaseAlbumPlaylist):
22@dataclass
23class AlbumPlaylist(BaseAlbumPlaylist):
24    """Playlist or album with full user info"""
25
26    user: User

Playlist or album with full user info

AlbumPlaylist( artwork_url: Optional[str], created_at: datetime.datetime, description: Optional[str], duration: int, embeddable_by: str, genre: Optional[str], id: int, kind: str, label_name: Optional[str], last_modified: datetime.datetime, licence: Optional[str], likes_count: Optional[int], permalink: str, permalink_url: str, public: bool, purchase_title: Optional[str], purchase_url: Optional[str], release_date: Optional[str], reposts_count: Optional[int], secret_token: Optional[str], sharing: str, tag_list: str, title: str, uri: str, user_id: int, display_date: str, managed_by_feeds: bool, set_type: str, is_album: bool, published_at: Optional[datetime.datetime], track_count: int, tracks: Tuple[Union[BasicTrack, MiniTrack], ...], user: User)
user: User
@dataclass
class AlbumPlaylistNoTracks(soundcloud.resource.base.BaseData):
36@dataclass
37class AlbumPlaylistNoTracks(BaseData):
38    """Playlist or album with no track info"""
39
40    artwork_url: Optional[str]
41    created_at: datetime.datetime
42    duration: int
43    id: int
44    kind: str
45    last_modified: datetime.datetime
46    likes_count: Optional[int]
47    managed_by_feeds: bool
48    permalink: str
49    permalink_url: str
50    public: bool
51    reposts_count: Optional[int]
52    secret_token: Optional[str]
53    sharing: str
54    title: str
55    track_count: int
56    uri: str
57    user_id: int
58    set_type: str
59    is_album: bool
60    published_at: Optional[datetime.datetime]
61    release_date: Optional[str]
62    display_date: datetime.datetime
63    user: BasicUser

Playlist or album with no track info

AlbumPlaylistNoTracks( artwork_url: Optional[str], created_at: datetime.datetime, duration: int, id: int, kind: str, last_modified: datetime.datetime, likes_count: Optional[int], managed_by_feeds: bool, permalink: str, permalink_url: str, public: bool, reposts_count: Optional[int], secret_token: Optional[str], sharing: str, title: str, track_count: int, uri: str, user_id: int, set_type: str, is_album: bool, published_at: Optional[datetime.datetime], release_date: Optional[str], display_date: datetime.datetime, user: BasicUser)
artwork_url: Optional[str]
created_at: datetime.datetime
duration: int
id: int
kind: str
last_modified: datetime.datetime
likes_count: Optional[int]
managed_by_feeds: bool
public: bool
reposts_count: Optional[int]
secret_token: Optional[str]
sharing: str
title: str
track_count: int
uri: str
user_id: int
set_type: str
is_album: bool
published_at: Optional[datetime.datetime]
release_date: Optional[str]
display_date: datetime.datetime
user: BasicUser
@dataclass
class BasicAlbumPlaylist(soundcloud.resource.playlist.BaseAlbumPlaylist):
29@dataclass
30class BasicAlbumPlaylist(BaseAlbumPlaylist):
31    """Playlist or album with partial user info"""
32
33    user: BasicUser

Playlist or album with partial user info

BasicAlbumPlaylist( artwork_url: Optional[str], created_at: datetime.datetime, description: Optional[str], duration: int, embeddable_by: str, genre: Optional[str], id: int, kind: str, label_name: Optional[str], last_modified: datetime.datetime, licence: Optional[str], likes_count: Optional[int], permalink: str, permalink_url: str, public: bool, purchase_title: Optional[str], purchase_url: Optional[str], release_date: Optional[str], reposts_count: Optional[int], secret_token: Optional[str], sharing: str, tag_list: str, title: str, uri: str, user_id: int, display_date: str, managed_by_feeds: bool, set_type: str, is_album: bool, published_at: Optional[datetime.datetime], track_count: int, tracks: Tuple[Union[BasicTrack, MiniTrack], ...], user: BasicUser)
user: BasicUser
@dataclass
class PlaylistStreamItem(soundcloud.resource.stream.BaseStreamItem):
47@dataclass
48class PlaylistStreamItem(BaseStreamItem):
49    """Album or playlist post in user's feed"""
50
51    playlist: BasicAlbumPlaylist

Album or playlist post in user's feed

PlaylistStreamItem( created_at: datetime.datetime, type: str, user: BasicUser, uuid: str, caption: Optional[str], playlist: BasicAlbumPlaylist)
playlist: BasicAlbumPlaylist
@dataclass
class PlaylistStreamRepostItem(soundcloud.resource.stream.BaseStreamRepostItem):
54@dataclass
55class PlaylistStreamRepostItem(BaseStreamRepostItem):
56    """Album or playlist repost in user's feed"""
57
58    playlist: BasicAlbumPlaylist

Album or playlist repost in user's feed

PlaylistStreamRepostItem( created_at: datetime.datetime, type: str, user: BasicUser, uuid: str, caption: Optional[str], reposted: Optional[soundcloud.resource.stream.Reposted], playlist: BasicAlbumPlaylist)
playlist: BasicAlbumPlaylist
@dataclass
class TrackStreamItem(soundcloud.resource.stream.BaseStreamItem):
33@dataclass
34class TrackStreamItem(BaseStreamItem):
35    """Track post in user's feed"""
36
37    track: BasicTrack

Track post in user's feed

TrackStreamItem( created_at: datetime.datetime, type: str, user: BasicUser, uuid: str, caption: Optional[str], track: BasicTrack)
track: BasicTrack
@dataclass
class TrackStreamRepostItem(soundcloud.resource.stream.BaseStreamRepostItem):
40@dataclass
41class TrackStreamRepostItem(BaseStreamRepostItem):
42    """Track repost in user's feed"""
43
44    track: BasicTrack

Track repost in user's feed

TrackStreamRepostItem( created_at: datetime.datetime, type: str, user: BasicUser, uuid: str, caption: Optional[str], reposted: Optional[soundcloud.resource.stream.Reposted], track: BasicTrack)
track: BasicTrack
@dataclass
class BasicTrack(soundcloud.resource.track.BaseTrack):
80@dataclass
81class BasicTrack(BaseTrack):
82    """Track with partial user info"""
83
84    user: BasicUser

Track with partial user info

BasicTrack( artwork_url: Optional[str], created_at: datetime.datetime, description: Optional[str], duration: int, embeddable_by: str, genre: Optional[str], id: int, kind: str, label_name: Optional[str], last_modified: datetime.datetime, licence: Optional[str], likes_count: Optional[int], permalink: str, permalink_url: str, public: bool, purchase_title: Optional[str], purchase_url: Optional[str], release_date: Optional[str], reposts_count: Optional[int], secret_token: Optional[str], sharing: str, tag_list: str, title: str, uri: str, user_id: int, display_date: str, caption: Optional[str], commentable: bool, comment_count: Optional[int], downloadable: bool, download_count: Optional[int], full_duration: int, has_downloads_left: bool, playback_count: Optional[int], state: str, streamable: bool, urn: str, visuals: Optional[Visuals], waveform_url: str, media: Media, station_urn: Optional[str], station_permalink: Optional[str], track_authorization: str, monetization_model: str, policy: str, user: BasicUser)
user: BasicUser
@dataclass
class Format(soundcloud.resource.base.BaseData):
12@dataclass
13class Format(BaseData):
14    """Track file format"""
15
16    protocol: str
17    mime_type: str

Track file format

Format(protocol: str, mime_type: str)
protocol: str
mime_type: str
@dataclass
class Media(soundcloud.resource.base.BaseData):
32@dataclass
33class Media(BaseData):
34    """List of available transcodings"""
35
36    transcodings: Tuple[Transcoding, ...]

List of available transcodings

Media(transcodings: Tuple[Transcoding, ...])
transcodings: Tuple[Transcoding, ...]
@dataclass
class MiniTrack(soundcloud.resource.base.BaseData):
87@dataclass
88class MiniTrack(BaseData):
89    """Track with minimal info"""
90
91    id: int
92    kind: str
93    monetization_model: str
94    policy: str

Track with minimal info

MiniTrack(id: int, kind: str, monetization_model: str, policy: str)
id: int
kind: str
monetization_model: str
policy: str
@dataclass
class PublisherMetadata(soundcloud.resource.base.BaseData):
39@dataclass
40class PublisherMetadata(BaseData):
41    """Publisher info"""
42
43    id: str
44    urn: str
45    contains_music: bool

Publisher info

PublisherMetadata(id: str, urn: str, contains_music: bool)
id: str
urn: str
contains_music: bool
@dataclass
class Track(soundcloud.resource.track.BaseTrack):
73@dataclass
74class Track(BaseTrack):
75    """Track with full user info"""
76
77    user: User

Track with full user info

Track( artwork_url: Optional[str], created_at: datetime.datetime, description: Optional[str], duration: int, embeddable_by: str, genre: Optional[str], id: int, kind: str, label_name: Optional[str], last_modified: datetime.datetime, licence: Optional[str], likes_count: Optional[int], permalink: str, permalink_url: str, public: bool, purchase_title: Optional[str], purchase_url: Optional[str], release_date: Optional[str], reposts_count: Optional[int], secret_token: Optional[str], sharing: str, tag_list: str, title: str, uri: str, user_id: int, display_date: str, caption: Optional[str], commentable: bool, comment_count: Optional[int], downloadable: bool, download_count: Optional[int], full_duration: int, has_downloads_left: bool, playback_count: Optional[int], state: str, streamable: bool, urn: str, visuals: Optional[Visuals], waveform_url: str, media: Media, station_urn: Optional[str], station_permalink: Optional[str], track_authorization: str, monetization_model: str, policy: str, user: User)
user: User
@dataclass
class Transcoding(soundcloud.resource.base.BaseData):
20@dataclass
21class Transcoding(BaseData):
22    """Available transcoding for track"""
23
24    url: str
25    preset: str
26    duration: int
27    snipped: bool
28    format: Format
29    quality: str

Available transcoding for track

Transcoding( url: str, preset: str, duration: int, snipped: bool, format: Format, quality: str)
url: str
preset: str
duration: int
snipped: bool
format: Format
quality: str
@dataclass
class CommentTrack(soundcloud.resource.base.BaseData):
 97@dataclass
 98class CommentTrack(BaseData):
 99    """Track with partial info"""
100
101    artwork_url: Optional[str]
102    caption: Optional[str]
103    id: int
104    kind: str
105    last_modified: datetime.datetime
106    permalink: str
107    permalink_url: str
108    public: bool
109    secret_token: Optional[str]
110    sharing: str
111    title: str
112    uri: str
113    urn: str
114    user_id: int
115    full_duration: int
116    duration: int
117    display_date: datetime.datetime
118    media: Media
119    station_urn: Optional[str]
120    station_permalink: Optional[str]
121    track_authorization: str
122    monetization_model: str
123    policy: str
124    user: BasicUser

Track with partial info

CommentTrack( artwork_url: Optional[str], caption: Optional[str], id: int, kind: str, last_modified: datetime.datetime, permalink: str, permalink_url: str, public: bool, secret_token: Optional[str], sharing: str, title: str, uri: str, urn: str, user_id: int, full_duration: int, duration: int, display_date: datetime.datetime, media: Media, station_urn: Optional[str], station_permalink: Optional[str], track_authorization: str, monetization_model: str, policy: str, user: BasicUser)
artwork_url: Optional[str]
caption: Optional[str]
id: int
kind: str
last_modified: datetime.datetime
public: bool
secret_token: Optional[str]
sharing: str
title: str
uri: str
urn: str
user_id: int
full_duration: int
duration: int
display_date: datetime.datetime
media: Media
station_urn: Optional[str]
track_authorization: str
monetization_model: str
policy: str
user: BasicUser
@dataclass
class Badges(soundcloud.resource.base.BaseData):
20@dataclass
21class Badges(BaseData):
22    """User badges"""
23
24    pro: bool
25    pro_unlimited: bool
26    verified: bool

User badges

Badges(pro: bool, pro_unlimited: bool, verified: bool)
pro: bool
pro_unlimited: bool
verified: bool
@dataclass
class BasicUser(soundcloud.resource.base.BaseData):
29@dataclass
30class BasicUser(BaseData):
31    """User with partial information"""
32
33    avatar_url: str
34    first_name: str
35    followers_count: int
36    full_name: str
37    id: int
38    kind: str
39    last_modified: datetime.datetime
40    last_name: str
41    permalink: str
42    permalink_url: str
43    uri: str
44    urn: str
45    username: str
46    verified: bool
47    city: Optional[str]
48    country_code: Optional[str]
49    badges: Badges
50    station_urn: Optional[str]
51    station_permalink: Optional[str]

User with partial information

BasicUser( avatar_url: str, first_name: str, followers_count: int, full_name: str, id: int, kind: str, last_modified: datetime.datetime, last_name: str, permalink: str, permalink_url: str, uri: str, urn: str, username: str, verified: bool, city: Optional[str], country_code: Optional[str], badges: Badges, station_urn: Optional[str], station_permalink: Optional[str])
avatar_url: str
first_name: str
followers_count: int
full_name: str
id: int
kind: str
last_modified: datetime.datetime
last_name: str
uri: str
urn: str
username: str
verified: bool
city: Optional[str]
country_code: Optional[str]
badges: Badges
station_urn: Optional[str]
@dataclass
class CreatorSubscription(soundcloud.resource.base.BaseData):
15@dataclass
16class CreatorSubscription(BaseData):
17    product: Product
CreatorSubscription(product: Product)
product: Product
@dataclass
class Product(soundcloud.resource.base.BaseData):
10@dataclass
11class Product(BaseData):
12    id: str
Product(id: str)
id: str
@dataclass
class User(soundcloud.BasicUser):
54@dataclass
55class User(BasicUser):
56    """User with full information"""
57
58    comments_count: int
59    created_at: Optional[datetime.datetime]
60    creator_subscriptions: Tuple[CreatorSubscription, ...]
61    creator_subscription: CreatorSubscription
62    description: Optional[str]
63    followings_count: int
64    groups_count: int
65    likes_count: Optional[int]
66    playlist_likes_count: Optional[int]
67    playlist_count: int
68    reposts_count: Optional[int]
69    track_count: int
70    visuals: Optional[Visuals]

User with full information

User( avatar_url: str, first_name: str, followers_count: int, full_name: str, id: int, kind: str, last_modified: datetime.datetime, last_name: str, permalink: str, permalink_url: str, uri: str, urn: str, username: str, verified: bool, city: Optional[str], country_code: Optional[str], badges: Badges, station_urn: Optional[str], station_permalink: Optional[str], comments_count: int, created_at: Optional[datetime.datetime], creator_subscriptions: Tuple[CreatorSubscription, ...], creator_subscription: CreatorSubscription, description: Optional[str], followings_count: int, groups_count: int, likes_count: Optional[int], playlist_likes_count: Optional[int], playlist_count: int, reposts_count: Optional[int], track_count: int, visuals: Optional[Visuals])
comments_count: int
created_at: Optional[datetime.datetime]
creator_subscriptions: Tuple[CreatorSubscription, ...]
creator_subscription: CreatorSubscription
description: Optional[str]
followings_count: int
groups_count: int
likes_count: Optional[int]
playlist_likes_count: Optional[int]
playlist_count: int
reposts_count: Optional[int]
track_count: int
visuals: Optional[Visuals]
@dataclass
class UserEmail(soundcloud.resource.base.BaseData):
87@dataclass
88class UserEmail(BaseData):
89    """Email address associated with a user"""
90
91    address: str
92    confirmed: bool
93    id: int
94    kind: str
95    last_modified: datetime.datetime
96    primary: bool
97    urn: str
98    user_id: str

Email address associated with a user

UserEmail( address: str, confirmed: bool, id: int, kind: str, last_modified: datetime.datetime, primary: bool, urn: str, user_id: str)
address: str
confirmed: bool
id: int
kind: str
last_modified: datetime.datetime
primary: bool
urn: str
user_id: str
@dataclass
class Visual(soundcloud.resource.base.BaseData):
 8@dataclass
 9class Visual(BaseData):
10    urn: str
11    entry_time: int
12    visual_url: str
Visual(urn: str, entry_time: int, visual_url: str)
urn: str
entry_time: int
visual_url: str
@dataclass
class Visuals(soundcloud.resource.base.BaseData):
15@dataclass
16class Visuals(BaseData):
17    urn: str
18    enabled: bool
19    visuals: Tuple[Visual, ...]
Visuals( urn: str, enabled: bool, visuals: Tuple[Visual, ...])
urn: str
enabled: bool
visuals: Tuple[Visual, ...]
@dataclass
class WebProfile(soundcloud.resource.base.BaseData):
 8@dataclass
 9class WebProfile(BaseData):
10    url: str
11    network: str
12    title: str
13    username: Optional[str]
WebProfile(url: str, network: str, title: str, username: Optional[str])
url: str
network: str
title: str
username: Optional[str]
@dataclass
class NoContentResponse(soundcloud.resource.base.BaseData):
 7@dataclass
 8class NoContentResponse(BaseData):
 9    """Response with no content, mainly for DELETE requests"""
10
11    status_code: int

Response with no content, mainly for DELETE requests

NoContentResponse(status_code: int)
status_code: int