0
# Playlist Management
1
2
Comprehensive playlist operations including creation, modification, track management, collaboration features, and following functionality. Supports both current user's playlists and operations on other users' public playlists.
3
4
## Capabilities
5
6
### Playlist Information
7
8
Retrieve playlist details and metadata.
9
10
```python { .api }
11
def playlist(self, playlist_id, fields=None, market=None, additional_types=("track",)):
12
"""
13
Get playlist information.
14
15
Args:
16
playlist_id (str): Spotify playlist ID or URI
17
fields (str, optional): Comma-separated list of fields to return
18
market (str, optional): ISO 3166-1 alpha-2 country code
19
additional_types (tuple): Include 'episode' for podcast episodes (default: ("track",))
20
21
Returns:
22
dict: Playlist object with tracks, metadata, and owner information
23
"""
24
25
def current_user_playlists(self, limit=50, offset=0):
26
"""
27
Get current user's playlists.
28
29
Requires scope: playlist-read-private
30
31
Args:
32
limit (int): Number of playlists to return (1-50, default: 50)
33
offset (int): Index of first playlist (default: 0)
34
35
Returns:
36
dict: Paging object of simplified playlist objects
37
"""
38
39
def user_playlists(self, user, limit=50, offset=0):
40
"""
41
Get user's public playlists.
42
43
Args:
44
user (str): Spotify user ID
45
limit (int): Number of playlists to return (1-50, default: 50)
46
offset (int): Index of first playlist (default: 0)
47
48
Returns:
49
dict: Paging object of simplified playlist objects
50
"""
51
```
52
53
### Playlist Items and Tracks
54
55
Access and retrieve playlist content.
56
57
```python { .api }
58
def playlist_items(self, playlist_id, fields=None, limit=100, offset=0,
59
market=None, additional_types=("track", "episode")):
60
"""
61
Get playlist items (tracks and episodes).
62
63
Args:
64
playlist_id (str): Spotify playlist ID or URI
65
fields (str, optional): Comma-separated list of fields to return
66
limit (int): Number of items to return (1-100, default: 100)
67
offset (int): Index of first item (default: 0)
68
market (str, optional): ISO 3166-1 alpha-2 country code
69
additional_types (tuple): Content types to include (default: ("track", "episode"))
70
71
Returns:
72
dict: Paging object of playlist track objects with added_by and added_at info
73
"""
74
75
def playlist_tracks(self, playlist_id, fields=None, limit=100, offset=0,
76
market=None, additional_types=("track",)):
77
"""
78
Get playlist tracks (legacy method, use playlist_items instead).
79
80
Args:
81
playlist_id (str): Spotify playlist ID or URI
82
fields (str, optional): Comma-separated list of fields to return
83
limit (int): Number of tracks to return (1-100, default: 100)
84
offset (int): Index of first track (default: 0)
85
market (str, optional): ISO 3166-1 alpha-2 country code
86
additional_types (tuple): Content types to include (default: ("track",))
87
88
Returns:
89
dict: Paging object of playlist track objects
90
"""
91
92
def user_playlist(self, user, playlist_id=None, fields=None, market=None):
93
"""
94
Get user playlist (legacy method, use playlist instead).
95
96
Args:
97
user (str): Spotify user ID (ignored in current API)
98
playlist_id (str): Spotify playlist ID or URI
99
fields (str, optional): Comma-separated list of fields to return
100
market (str, optional): ISO 3166-1 alpha-2 country code
101
102
Returns:
103
dict: Playlist object
104
"""
105
106
def user_playlist_tracks(self, user, playlist_id, fields=None, limit=100,
107
offset=0, market=None):
108
"""
109
Get user playlist tracks (legacy method, use playlist_tracks instead).
110
111
Args:
112
user (str): Spotify user ID (ignored in current API)
113
playlist_id (str): Spotify playlist ID or URI
114
fields (str, optional): Comma-separated list of fields to return
115
limit (int): Number of tracks to return (1-100, default: 100)
116
offset (int): Index of first track (default: 0)
117
market (str, optional): ISO 3166-1 alpha-2 country code
118
119
Returns:
120
dict: Paging object of playlist track objects
121
"""
122
```
123
124
### Playlist Creation and Modification
125
126
Create new playlists and modify existing ones.
127
128
```python { .api }
129
def user_playlist_create(self, user, name, public=True, collaborative=False, description=""):
130
"""
131
Create playlist for user (legacy method).
132
133
Requires scope: playlist-modify-public or playlist-modify-private
134
135
Args:
136
user (str): Spotify user ID (must be current user)
137
name (str): Playlist name
138
public (bool): Make playlist public (default: True)
139
collaborative (bool): Make playlist collaborative (default: False)
140
description (str): Playlist description (default: "")
141
142
Returns:
143
dict: Created playlist object
144
"""
145
146
def playlist_change_details(self, playlist_id, name=None, public=None,
147
collaborative=None, description=None):
148
"""
149
Change playlist details.
150
151
Requires scope: playlist-modify-public or playlist-modify-private
152
153
Args:
154
playlist_id (str): Spotify playlist ID or URI
155
name (str, optional): New playlist name
156
public (bool, optional): Make playlist public/private
157
collaborative (bool, optional): Make playlist collaborative
158
description (str, optional): New playlist description
159
160
Returns:
161
None
162
"""
163
164
def user_playlist_change_details(self, user, playlist_id, name=None, public=None,
165
collaborative=None, description=None):
166
"""
167
Change user playlist details (legacy method, use playlist_change_details instead).
168
169
Requires scope: playlist-modify-public or playlist-modify-private
170
171
Args:
172
user (str): Spotify user ID (ignored in current API)
173
playlist_id (str): Spotify playlist ID or URI
174
name (str, optional): New playlist name
175
public (bool, optional): Make playlist public/private
176
collaborative (bool, optional): Make playlist collaborative
177
description (str, optional): New playlist description
178
179
Returns:
180
None
181
"""
182
```
183
184
### Adding Items to Playlists
185
186
Add tracks and episodes to playlists.
187
188
```python { .api }
189
def playlist_add_items(self, playlist_id, items, position=None):
190
"""
191
Add items to playlist.
192
193
Requires scope: playlist-modify-public or playlist-modify-private
194
195
Args:
196
playlist_id (str): Spotify playlist ID or URI
197
items (list): List of track/episode URIs to add (max 100)
198
position (int, optional): Position to insert items (default: end)
199
200
Returns:
201
dict: Object with snapshot_id for the updated playlist
202
"""
203
204
def user_playlist_add_tracks(self, user, playlist_id, tracks, position=None):
205
"""
206
Add tracks to user playlist (legacy method, use playlist_add_items instead).
207
208
Requires scope: playlist-modify-public or playlist-modify-private
209
210
Args:
211
user (str): Spotify user ID (ignored in current API)
212
playlist_id (str): Spotify playlist ID or URI
213
tracks (list): List of track URIs to add (max 100)
214
position (int, optional): Position to insert tracks (default: end)
215
216
Returns:
217
dict: Object with snapshot_id for the updated playlist
218
"""
219
220
def user_playlist_add_episodes(self, user, playlist_id, episodes, position=None):
221
"""
222
Add episodes to user playlist (legacy method, use playlist_add_items instead).
223
224
Requires scope: playlist-modify-public or playlist-modify-private
225
226
Args:
227
user (str): Spotify user ID (ignored in current API)
228
playlist_id (str): Spotify playlist ID or URI
229
episodes (list): List of episode URIs to add (max 100)
230
position (int, optional): Position to insert episodes (default: end)
231
232
Returns:
233
dict: Object with snapshot_id for the updated playlist
234
"""
235
```
236
237
### Replacing and Reordering Items
238
239
Replace playlist contents and reorder items.
240
241
```python { .api }
242
def playlist_replace_items(self, playlist_id, items):
243
"""
244
Replace all items in playlist.
245
246
Requires scope: playlist-modify-public or playlist-modify-private
247
248
Args:
249
playlist_id (str): Spotify playlist ID or URI
250
items (list): List of track/episode URIs to replace with (max 100)
251
252
Returns:
253
dict: Object with snapshot_id for the updated playlist
254
"""
255
256
def user_playlist_replace_tracks(self, user, playlist_id, tracks):
257
"""
258
Replace all tracks in user playlist (legacy method, use playlist_replace_items instead).
259
260
Requires scope: playlist-modify-public or playlist-modify-private
261
262
Args:
263
user (str): Spotify user ID (ignored in current API)
264
playlist_id (str): Spotify playlist ID or URI
265
tracks (list): List of track URIs to replace with (max 100)
266
267
Returns:
268
dict: Object with snapshot_id for the updated playlist
269
"""
270
271
def playlist_reorder_items(self, playlist_id, range_start, insert_before,
272
range_length=1, snapshot_id=None):
273
"""
274
Reorder items in playlist.
275
276
Requires scope: playlist-modify-public or playlist-modify-private
277
278
Args:
279
playlist_id (str): Spotify playlist ID or URI
280
range_start (int): Position of first item to move
281
insert_before (int): Position to insert the items
282
range_length (int): Number of items to move (default: 1)
283
snapshot_id (str, optional): Playlist snapshot ID for consistency
284
285
Returns:
286
dict: Object with snapshot_id for the updated playlist
287
"""
288
289
def user_playlist_reorder_tracks(self, user, playlist_id, range_start, insert_before,
290
range_length=1, snapshot_id=None):
291
"""
292
Reorder tracks in user playlist (legacy method, use playlist_reorder_items instead).
293
294
Requires scope: playlist-modify-public or playlist-modify-private
295
296
Args:
297
user (str): Spotify user ID (ignored in current API)
298
playlist_id (str): Spotify playlist ID or URI
299
range_start (int): Position of first track to move
300
insert_before (int): Position to insert the tracks
301
range_length (int): Number of tracks to move (default: 1)
302
snapshot_id (str, optional): Playlist snapshot ID for consistency
303
304
Returns:
305
dict: Object with snapshot_id for the updated playlist
306
"""
307
```
308
309
### Removing Items from Playlists
310
311
Remove tracks and episodes from playlists.
312
313
```python { .api }
314
def playlist_remove_all_occurrences_of_items(self, playlist_id, items, snapshot_id=None):
315
"""
316
Remove all occurrences of items from playlist.
317
318
Requires scope: playlist-modify-public or playlist-modify-private
319
320
Args:
321
playlist_id (str): Spotify playlist ID or URI
322
items (list): List of track/episode URIs to remove (max 100)
323
snapshot_id (str, optional): Playlist snapshot ID for consistency
324
325
Returns:
326
dict: Object with snapshot_id for the updated playlist
327
"""
328
329
def playlist_remove_specific_occurrences_of_items(self, playlist_id, items, snapshot_id=None):
330
"""
331
Remove specific occurrences of items from playlist.
332
333
Requires scope: playlist-modify-public or playlist-modify-private
334
335
Args:
336
playlist_id (str): Spotify playlist ID or URI
337
items (list): List of objects with 'uri' and 'positions' keys (max 100)
338
snapshot_id (str, optional): Playlist snapshot ID for consistency
339
340
Returns:
341
dict: Object with snapshot_id for the updated playlist
342
"""
343
344
def user_playlist_remove_all_occurrences_of_tracks(self, user, playlist_id, tracks, snapshot_id=None):
345
"""
346
Remove all occurrences of tracks from user playlist (legacy method).
347
348
Requires scope: playlist-modify-public or playlist-modify-private
349
350
Args:
351
user (str): Spotify user ID (ignored in current API)
352
playlist_id (str): Spotify playlist ID or URI
353
tracks (list): List of track URIs to remove (max 100)
354
snapshot_id (str, optional): Playlist snapshot ID for consistency
355
356
Returns:
357
dict: Object with snapshot_id for the updated playlist
358
"""
359
360
def user_playlist_remove_specific_occurrences_of_tracks(self, user, playlist_id, tracks,
361
positions, snapshot_id=None):
362
"""
363
Remove specific occurrences of tracks from user playlist (legacy method).
364
365
Requires scope: playlist-modify-public or playlist-modify-private
366
367
Args:
368
user (str): Spotify user ID (ignored in current API)
369
playlist_id (str): Spotify playlist ID or URI
370
tracks (list): List of track URIs to remove
371
positions (list): List of positions for each track URI
372
snapshot_id (str, optional): Playlist snapshot ID for consistency
373
374
Returns:
375
dict: Object with snapshot_id for the updated playlist
376
"""
377
```
378
379
### Following Playlists
380
381
Follow and unfollow playlists, check following status.
382
383
```python { .api }
384
def current_user_follow_playlist(self, playlist_id, public=True):
385
"""
386
Follow playlist.
387
388
Requires scope: playlist-modify-public or playlist-modify-private
389
390
Args:
391
playlist_id (str): Spotify playlist ID or URI
392
public (bool): Show as public in user's profile (default: True)
393
394
Returns:
395
None
396
"""
397
398
def current_user_unfollow_playlist(self, playlist_id):
399
"""
400
Unfollow playlist.
401
402
Requires scope: playlist-modify-public or playlist-modify-private
403
404
Args:
405
playlist_id (str): Spotify playlist ID or URI
406
407
Returns:
408
None
409
"""
410
411
def playlist_is_following(self, playlist_id, user_ids):
412
"""
413
Check if users follow playlist.
414
415
Args:
416
playlist_id (str): Spotify playlist ID or URI
417
user_ids (list): List of user IDs to check (max 5)
418
419
Returns:
420
list: Boolean list indicating which users follow the playlist
421
"""
422
423
def user_playlist_follow_playlist(self, playlist_owner_id, playlist_id):
424
"""
425
Follow playlist (legacy method, use current_user_follow_playlist instead).
426
427
Requires scope: playlist-modify-public or playlist-modify-private
428
429
Args:
430
playlist_owner_id (str): Playlist owner's user ID (ignored in current API)
431
playlist_id (str): Spotify playlist ID or URI
432
433
Returns:
434
None
435
"""
436
437
def user_playlist_unfollow(self, user, playlist_id):
438
"""
439
Unfollow playlist (legacy method, use current_user_unfollow_playlist instead).
440
441
Requires scope: playlist-modify-public or playlist-modify-private
442
443
Args:
444
user (str): User ID (ignored in current API)
445
playlist_id (str): Spotify playlist ID or URI
446
447
Returns:
448
None
449
"""
450
451
def user_playlist_is_following(self, playlist_owner_id, playlist_id, user_ids):
452
"""
453
Check if users follow playlist (legacy method, use playlist_is_following instead).
454
455
Args:
456
playlist_owner_id (str): Playlist owner's user ID (ignored in current API)
457
playlist_id (str): Spotify playlist ID or URI
458
user_ids (list): List of user IDs to check (max 5)
459
460
Returns:
461
list: Boolean list indicating which users follow the playlist
462
"""
463
```
464
465
### Playlist Cover Images
466
467
Manage playlist cover images.
468
469
```python { .api }
470
def playlist_cover_image(self, playlist_id):
471
"""
472
Get playlist cover image.
473
474
Args:
475
playlist_id (str): Spotify playlist ID or URI
476
477
Returns:
478
list: List of image objects with URL, height, and width
479
"""
480
481
def playlist_upload_cover_image(self, playlist_id, image_b64):
482
"""
483
Upload custom playlist cover image.
484
485
Requires scope: ugc-image-upload, playlist-modify-public or playlist-modify-private
486
487
Args:
488
playlist_id (str): Spotify playlist ID or URI
489
image_b64 (str): Base64 encoded JPEG image data (max 256KB)
490
491
Returns:
492
None
493
"""
494
```
495
496
## Usage Examples
497
498
### Creating and Managing Playlists
499
500
```python
501
import spotipy
502
from spotipy.oauth2 import SpotifyOAuth
503
504
scope = "playlist-modify-public playlist-modify-private"
505
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope))
506
507
# Get current user ID
508
user = sp.me()
509
user_id = user['id']
510
511
# Create a new playlist
512
playlist = sp.user_playlist_create(
513
user=user_id,
514
name="My Awesome Playlist",
515
description="Created with Spotipy",
516
public=True
517
)
518
519
print(f"Created playlist: {playlist['name']} (ID: {playlist['id']})")
520
521
# Add tracks to the playlist
522
track_uris = [
523
'spotify:track:4iV5W9uYEdYUVa79Axb7Rh', # Mr. Brightside
524
'spotify:track:0VjIjW4GlUAb6qAOLklx2J', # Bohemian Rhapsody
525
'spotify:track:1301WleyT98MSxVHPZCA6M' # Sweet Child O' Mine
526
]
527
528
result = sp.playlist_add_items(playlist['id'], track_uris)
529
print(f"Added {len(track_uris)} tracks. Snapshot ID: {result['snapshot_id']}")
530
531
# Update playlist details
532
sp.playlist_change_details(
533
playlist['id'],
534
name="My Updated Playlist",
535
description="Updated description with more details",
536
public=False # Make it private
537
)
538
print("Playlist details updated")
539
```
540
541
### Managing Playlist Content
542
543
```python
544
playlist_id = "37i9dQZF1DXcBWIGoYBM5M" # Example playlist ID
545
546
# Get playlist information
547
playlist_info = sp.playlist(playlist_id)
548
print(f"Playlist: {playlist_info['name']} by {playlist_info['owner']['display_name']}")
549
print(f"Tracks: {playlist_info['tracks']['total']}")
550
print(f"Followers: {playlist_info['followers']['total']}")
551
552
# Get all tracks from playlist
553
tracks = []
554
results = sp.playlist_items(playlist_id, limit=50)
555
tracks.extend(results['items'])
556
557
while results['next']:
558
results = sp.next(results)
559
tracks.extend(results['items'])
560
561
print(f"\\nAll {len(tracks)} tracks:")
562
for i, item in enumerate(tracks[:10], 1): # Show first 10
563
track = item['track']
564
if track: # Check if track is not None (could be deleted)
565
artist_names = ', '.join([artist['name'] for artist in track['artists']])
566
print(f" {i}. {track['name']} - {artist_names}")
567
print(f" Added by: {item['added_by']['id']} on {item['added_at'][:10]}")
568
```
569
570
### Playlist Collaboration
571
572
```python
573
# Create a collaborative playlist
574
collaborative_playlist = sp.user_playlist_create(
575
user=user_id,
576
name="Team Collaborative Playlist",
577
description="Add your favorite tracks!",
578
collaborative=True,
579
public=False # Private but collaborative
580
)
581
582
print(f"Created collaborative playlist: {collaborative_playlist['external_urls']['spotify']}")
583
584
# Check who's following a playlist
585
user_ids_to_check = ['spotify', 'example_user', user_id]
586
following_status = sp.playlist_is_following(collaborative_playlist['id'], user_ids_to_check)
587
588
for user_id_check, is_following in zip(user_ids_to_check, following_status):
589
status = "following" if is_following else "not following"
590
print(f"User {user_id_check} is {status} the playlist")
591
```
592
593
### Advanced Playlist Operations
594
595
```python
596
# Reorder tracks in playlist
597
my_playlist_id = "your_playlist_id_here"
598
599
# Move track at position 0 to position 5
600
result = sp.playlist_reorder_items(
601
playlist_id=my_playlist_id,
602
range_start=0, # Move track at position 0
603
insert_before=6, # Insert before position 6 (so it ends up at position 5)
604
range_length=1 # Move 1 track
605
)
606
print(f"Reordered playlist. New snapshot: {result['snapshot_id']}")
607
608
# Remove specific occurrences of tracks
609
tracks_to_remove = [
610
{
611
"uri": "spotify:track:4iV5W9uYEdYUVa79Axb7Rh",
612
"positions": [0, 3] # Remove from positions 0 and 3
613
}
614
]
615
616
result = sp.playlist_remove_specific_occurrences_of_items(
617
my_playlist_id,
618
tracks_to_remove
619
)
620
print(f"Removed specific track occurrences. New snapshot: {result['snapshot_id']}")
621
622
# Replace entire playlist content
623
new_track_uris = [
624
'spotify:track:0VjIjW4GlUAOLklx2J',
625
'spotify:track:1301WleyT98MSxVHPZCA6M',
626
'spotify:track:4VqPOruhp5EdPBeR92t6lQ'
627
]
628
629
result = sp.playlist_replace_items(my_playlist_id, new_track_uris)
630
print(f"Replaced all playlist content. New snapshot: {result['snapshot_id']}")
631
```
632
633
### Working with Playlist Images
634
635
```python
636
import base64
637
638
# Get current playlist cover
639
cover_images = sp.playlist_cover_image(playlist_id)
640
if cover_images:
641
print(f"Current cover image: {cover_images[0]['url']}")
642
print(f"Dimensions: {cover_images[0]['width']}x{cover_images[0]['height']}")
643
644
# Upload custom cover image
645
# Note: Image must be JPEG format, base64 encoded, max 256KB
646
with open("my_playlist_cover.jpg", "rb") as image_file:
647
image_b64 = base64.b64encode(image_file.read()).decode('utf-8')
648
649
try:
650
sp.playlist_upload_cover_image(playlist_id, image_b64)
651
print("Successfully uploaded custom playlist cover!")
652
except Exception as e:
653
print(f"Failed to upload cover: {e}")
654
```
655
656
### Bulk Playlist Operations
657
658
```python
659
# Get all user's playlists
660
all_playlists = []
661
results = sp.current_user_playlists(limit=50)
662
all_playlists.extend(results['items'])
663
664
while results['next']:
665
results = sp.next(results)
666
all_playlists.extend(results['items'])
667
668
print(f"Found {len(all_playlists)} playlists")
669
670
# Analyze playlists
671
total_tracks = 0
672
collaborative_count = 0
673
public_count = 0
674
675
for playlist in all_playlists:
676
total_tracks += playlist['tracks']['total']
677
if playlist['collaborative']:
678
collaborative_count += 1
679
if playlist['public']:
680
public_count += 1
681
682
print(f"Total tracks across all playlists: {total_tracks}")
683
print(f"Collaborative playlists: {collaborative_count}")
684
print(f"Public playlists: {public_count}")
685
print(f"Private playlists: {len(all_playlists) - public_count}")
686
687
# Find largest playlists
688
largest_playlists = sorted(all_playlists, key=lambda x: x['tracks']['total'], reverse=True)[:5]
689
print("\\nLargest playlists:")
690
for playlist in largest_playlists:
691
print(f" {playlist['name']}: {playlist['tracks']['total']} tracks")
692
```
693
694
## Required Scopes Summary
695
696
- **playlist-read-private**: Read user's private playlists
697
- **playlist-read-collaborative**: Read user's collaborative playlists
698
- **playlist-modify-public**: Create and modify user's public playlists
699
- **playlist-modify-private**: Create and modify user's private playlists
700
- **ugc-image-upload**: Upload custom playlist cover images