A Python interface to Last.fm and Libre.fm for music data, scrobbling, and social features.
—
User profiles, listening history, social interactions, library access, and community features. This covers comprehensive user data access, social networking capabilities, and music library management through PyLast's user-centric objects.
Core user representation with profile information, statistics, and listening data access.
class User:
"""
Represents a Last.fm user.
Args:
user_name (str): Username
network: Network instance (LastFMNetwork or LibreFMNetwork)
"""
def __init__(self, user_name: str, network): ...
def get_name(self, properly_capitalized=False) -> str:
"""
Get username.
Args:
properly_capitalized (bool): Return properly capitalized username
Returns:
str: Username
"""
def get_playcount(self) -> int:
"""Get total play count for this user."""
def get_country(self) -> Country:
"""Get user's country as Country object."""
def is_subscriber(self) -> bool:
"""Check if user is a Last.fm subscriber."""
def get_registered(self) -> str:
"""Get user registration date as string."""
def get_unixtime_registered(self) -> int:
"""Get user registration date as Unix timestamp."""
def get_image(self, size=2) -> str:
"""
Get user avatar image URL.
Args:
size (int): Image size (SIZE_SMALL to SIZE_MEGA)
Returns:
str: Avatar image URL
"""
def get_url(self, domain_name=0) -> str:
"""Get Last.fm profile URL for this user."""
class AuthenticatedUser(User):
"""
Represents the authenticated user (inherits from User).
Automatically uses the authenticated user's data without requiring username.
Args:
network: Network instance with valid session key
"""
def __init__(self, network): ...Access to user's music listening data, including recent tracks, loved tracks, and now playing information.
def get_recent_tracks(self, limit=50, cacheable=True, stream=True, from_date=None, to_date=None, time_from=None, time_to=None) -> list[PlayedTrack]:
"""
Get user's recent tracks.
Args:
limit (int): Maximum number of tracks to retrieve
cacheable (bool): Enable caching for this request
stream (bool): Include streaming tracks
from_date (str, optional): Start date (YYYY-MM-DD)
to_date (str, optional): End date (YYYY-MM-DD)
time_from (int, optional): Start timestamp
time_to (int, optional): End timestamp
Returns:
list[PlayedTrack]: Recent played tracks with timestamps
"""
def get_loved_tracks(self, limit=50, cacheable=True) -> list[LovedTrack]:
"""
Get user's loved tracks.
Args:
limit (int): Maximum number of tracks to retrieve
cacheable (bool): Enable caching for this request
Returns:
list[LovedTrack]: Loved tracks with timestamps
"""
def get_now_playing(self) -> Track | None:
"""
Get currently playing track.
Returns:
Track | None: Currently playing track, or None if nothing playing
"""
def get_track_scrobbles(self, artist: str, track: str, from_date=None, to_date=None) -> list[PlayedTrack]:
"""
Get scrobbles for a specific track.
Args:
artist (str): Artist name
track (str): Track name
from_date (str, optional): Start date (YYYY-MM-DD)
to_date (str, optional): End date (YYYY-MM-DD)
Returns:
list[PlayedTrack]: Scrobbles for the specified track
"""User's top artists, albums, tracks, and tags with customizable time periods.
def get_top_artists(self, period="overall", limit=None, cacheable=True) -> list[TopItem]:
"""
Get user's top artists.
Args:
period (str): Time period (PERIOD_OVERALL, PERIOD_7DAYS, etc.)
limit (int, optional): Maximum number of results
cacheable (bool): Enable caching for this request
Returns:
list[TopItem]: Top artists with play counts
"""
def get_top_albums(self, period="overall", limit=None, cacheable=True) -> list[TopItem]:
"""Get user's top albums for specified time period."""
def get_top_tracks(self, period="overall", limit=None, cacheable=True) -> list[TopItem]:
"""Get user's top tracks for specified time period."""
def get_top_tags(self, limit=None, cacheable=True) -> list[TopItem]:
"""Get user's top tags (most used tags)."""Access to user's tagged music content organized by tags.
def get_tagged_artists(self, tag: str, limit=None, cacheable=True) -> list[TopItem]:
"""
Get artists tagged by this user with specific tag.
Args:
tag (str): Tag name
limit (int, optional): Maximum number of results
cacheable (bool): Enable caching
Returns:
list[TopItem]: Artists tagged with specified tag
"""
def get_tagged_albums(self, tag: str, limit=None, cacheable=True) -> list[TopItem]:
"""Get albums tagged by this user with specific tag."""
def get_tagged_tracks(self, tag: str, limit=None, cacheable=True) -> list[TopItem]:
"""Get tracks tagged by this user with specific tag."""User's social network including friends and neighbors (users with similar taste).
def get_friends(self, limit=50, cacheable=True) -> list[User]:
"""
Get user's friends.
Args:
limit (int): Maximum number of friends to retrieve
cacheable (bool): Enable caching
Returns:
list[User]: Friend users
"""
def get_neighbours(self, limit=50, cacheable=True) -> list[User]:
"""
Get user's neighbors (users with similar music taste).
Args:
limit (int): Maximum number of neighbors to retrieve
cacheable (bool): Enable caching
Returns:
list[User]: Neighbor users
"""Access to user's music library with detailed play and tag statistics.
class Library:
"""
Represents a user's music library.
Args:
user: User object
network: Network instance
"""
def __init__(self, user, network): ...
def get_user(self) -> User:
"""Get the User object this library belongs to."""
def get_artists(self, limit=50, cacheable=True, stream=True) -> list[LibraryItem]:
"""
Get artists in user's library.
Args:
limit (int): Maximum number of artists to retrieve
cacheable (bool): Enable caching
stream (bool): Stream results for large libraries
Returns:
list[LibraryItem]: Library artists with play counts and tag counts
"""
# Access library through user object
def get_library(self) -> Library:
"""
Get user's library object.
Returns:
Library: User's music library
"""Historical weekly chart data for tracking music trends over time.
def get_weekly_chart_dates(self) -> list[tuple[str, str]]:
"""
Get available weekly chart date ranges.
Returns:
list[tuple[str, str]]: List of (from_date, to_date) tuples
"""
def get_weekly_artist_charts(self, from_date=None, to_date=None) -> list[TopItem]:
"""
Get weekly artist charts for date range.
Args:
from_date (str, optional): Start date
to_date (str, optional): End date
Returns:
list[TopItem]: Weekly top artists
"""
def get_weekly_album_charts(self, from_date=None, to_date=None) -> list[TopItem]:
"""Get weekly album charts for date range."""
def get_weekly_track_charts(self, from_date=None, to_date=None) -> list[TopItem]:
"""Get weekly track charts for date range."""Key data structures for user and social data.
from collections import namedtuple
PlayedTrack = namedtuple('PlayedTrack', ['track', 'album', 'playback_date', 'timestamp'])
"""
Represents a played track with timestamp.
Fields:
track (Track): The played track
album (Album): Album containing the track
playback_date (str): Human-readable playback date
timestamp (int): Unix timestamp of playback
"""
LovedTrack = namedtuple('LovedTrack', ['track', 'date', 'timestamp'])
"""
Represents a loved track with timestamp.
Fields:
track (Track): The loved track
date (str): Human-readable love date
timestamp (int): Unix timestamp when loved
"""
LibraryItem = namedtuple('LibraryItem', ['item', 'playcount', 'tagcount'])
"""
Represents a library item with statistics.
Fields:
item (Artist/Album/Track): The music item
playcount (int): Number of plays by the user
tagcount (int): Number of tags applied by the user
"""
TopItem = namedtuple('TopItem', ['item', 'weight'])
"""
Represents a top item with weight/ranking.
Fields:
item (Artist/Album/Track/Tag): The ranked item
weight (int): Ranking weight (higher = more popular)
"""import pylast
network = pylast.LastFMNetwork(api_key=API_KEY, api_secret=API_SECRET)
# Get user profile
user = network.get_user("username")
print(f"User: {user.get_name()}")
print(f"Country: {user.get_country().get_name()}")
print(f"Total plays: {user.get_playcount():,}")
print(f"Registered: {user.get_registered()}")
print(f"Subscriber: {user.is_subscriber()}")
# Get top artists for different periods
periods = [
("7day", "Last 7 Days"),
("1month", "Last Month"),
("6month", "Last 6 Months"),
("overall", "All Time")
]
for period_key, period_name in periods:
top_artists = user.get_top_artists(period=period_key, limit=5)
print(f"\nTop Artists - {period_name}:")
for i, artist_item in enumerate(top_artists, 1):
artist = artist_item.item
plays = artist_item.weight
print(f"{i}. {artist.get_name()} ({plays} plays)")# Get recent tracks
recent = user.get_recent_tracks(limit=20)
print("Recent Tracks:")
for played_track in recent:
track = played_track.track
album = played_track.album
date = played_track.playback_date
print(f"{track.get_artist().get_name()} - {track.get_title()}")
if album:
print(f" from '{album.get_title()}' on {date}")
else:
print(f" on {date}")
# Check what's currently playing
now_playing = user.get_now_playing()
if now_playing:
print(f"\nNow Playing: {now_playing.get_artist().get_name()} - {now_playing.get_title()}")
else:
print("\nNothing currently playing")# Get loved tracks
loved = user.get_loved_tracks(limit=10)
print("Loved Tracks:")
for loved_track in loved:
track = loved_track.track
date = loved_track.date
print(f"{track.get_artist().get_name()} - {track.get_title()} (loved on {date})")
# Get tagged content
rock_artists = user.get_tagged_artists("rock", limit=10)
print("\nArtists tagged as 'rock':")
for artist_item in rock_artists:
print(f"- {artist_item.item.get_name()}")
electronic_tracks = user.get_tagged_tracks("electronic", limit=5)
print("\nTracks tagged as 'electronic':")
for track_item in electronic_tracks:
track = track_item.item
print(f"- {track.get_artist().get_name()} - {track.get_title()}")# Get friends
friends = user.get_friends(limit=10)
print("Friends:")
for friend in friends:
print(f"- {friend.get_name()} ({friend.get_playcount():,} total plays)")
# Get music neighbors (similar taste)
neighbors = user.get_neighbours(limit=5)
print("\nMusic Neighbors (similar taste):")
for neighbor in neighbors:
print(f"- {neighbor.get_name()}")
# Compare top artists
neighbor_top = neighbor.get_top_artists(limit=3)
common_artists = []
user_top = user.get_top_artists(limit=10)
user_artist_names = {item.item.get_name().lower() for item in user_top}
for neighbor_artist in neighbor_top:
if neighbor_artist.item.get_name().lower() in user_artist_names:
common_artists.append(neighbor_artist.item.get_name())
if common_artists:
print(f" Common artists: {', '.join(common_artists)}")# Access user's library
library = user.get_library()
library_artists = library.get_artists(limit=50)
print("Library Analysis:")
print(f"Artists in library: {len(library_artists)}")
# Find most played artists
sorted_artists = sorted(library_artists, key=lambda x: x.playcount, reverse=True)
print("\nMost played artists in library:")
for i, lib_item in enumerate(sorted_artists[:10], 1):
artist = lib_item.item
plays = lib_item.playcount
tags = lib_item.tagcount
print(f"{i:2d}. {artist.get_name()} - {plays} plays, {tags} tags")
# Find most tagged artists
most_tagged = sorted(library_artists, key=lambda x: x.tagcount, reverse=True)
print("\nMost tagged artists:")
for lib_item in most_tagged[:5]:
if lib_item.tagcount > 0:
artist = lib_item.item
print(f"- {artist.get_name()} ({lib_item.tagcount} tags)")# Get available chart periods
chart_dates = user.get_weekly_chart_dates()
if chart_dates:
# Get recent weekly chart
latest_from, latest_to = chart_dates[-1]
weekly_artists = user.get_weekly_artist_charts(latest_from, latest_to)
print(f"Weekly Chart ({latest_from} to {latest_to}):")
for i, artist_item in enumerate(weekly_artists[:10], 1):
artist = artist_item.item
plays = artist_item.weight
print(f"{i:2d}. {artist.get_name()} ({plays} plays)")
# Compare with previous week if available
if len(chart_dates) > 1:
prev_from, prev_to = chart_dates[-2]
prev_weekly = user.get_weekly_artist_charts(prev_from, prev_to)
print(f"\nTrending (vs previous week):")
current_names = {item.item.get_name(): item.weight for item in weekly_artists[:10]}
prev_names = {item.item.get_name(): item.weight for item in prev_weekly}
for name, current_plays in current_names.items():
if name in prev_names:
change = current_plays - prev_names[name]
if change > 0:
print(f"↗ {name} (+{change} plays)")
elif change < 0:
print(f"↘ {name} ({change} plays)")
else:
print(f"★ {name} (new entry)")# For authenticated users (requires session key)
if network.session_key:
auth_user = network.get_authenticated_user()
# Same methods as regular User, but automatically uses authenticated user's data
my_recent = auth_user.get_recent_tracks(limit=5)
my_loved = auth_user.get_loved_tracks(limit=5)
print("My Recent Tracks:")
for played_track in my_recent:
track = played_track.track
print(f"- {track.get_artist().get_name()} - {track.get_title()}")
print("\nMy Loved Tracks:")
for loved_track in my_loved:
track = loved_track.track
print(f"♥ {track.get_artist().get_name()} - {track.get_title()}")Install with Tessl CLI
npx tessl i tessl/pypi-pylast