For the moment, Bluesky purports to believe you own your own attention. This means you choose how you engage with content on Bluesky, and can use the built-in algorithmic feeds provided by Bluesky, pick from published algorithmic feeds created by folks you trust, or build your own.
The URL for the “What’s Hot” feed gives us some information we can use to access it programmatically:
display_name
1 Mutuals
2 Best of Follows
3 Popular With Friends
4 Bluesky Team
5 What's Hot Classic
6 What's Hot
uri
1 at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/mutuals
2 at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/best-of-follows
3 at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/with-friends
4 at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/bsky-team
5 at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/hot-classic
6 at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot
We can use the “What’s Hot” URI to get a list of the items in that feed:
I’ve been glossing over the cursor slot in most of the return values since this is just a cookbook to get folks started. For any method that supports cursor-based pagination, you can add it as a parameter to the list. For example, this:
will get the next 50 (the current default page size) items in the feed.
Inside hot_feed has a feed slot which is a list of posts. Each post is a large, nested structure which we’ll look at via the Python object pretty-printed view of one example record:
FeedViewPost(
post=PostView(
author=ProfileViewBasic(
did='did:plc:xydmw4rhlnb4mrz5eyw3z6ak',
handle='yesitscolin.bsky.social',
avatar='https://cdn.bsky.social/imgproxy/_XZvSpVnwSOoZYun4CrxOERXmtD0FgOTz9ffXqbUnmE/rs:fill:1000:1000:1:0/plain/bafkreidluvoz62jftcf6iqsjjo7x46s237jbr6kkluecsallz6oci2k33q@jpeg',
displayName='Colin',
labels=[],
viewer=ViewerState(
blockedBy=False,
blocking=None,
followedBy=None,
following=None,
muted=False,
mutedByList=None,
_type='app.bsky.actor.defs#viewerState'
),
_type='app.bsky.actor.defs#profileViewBasic')
,
cid='bafyreigrcsumojr4k2cy7alnloeyxm464ab4exdt2orcfluvjzpe5t5uu4',
indexedAt='2023-07-08T13:16:24.879Z',
record=Main(
createdAt='2023-07-08T13:16:24.760Z',
text='Shoutout to everyone who still cuts these up before throwing them away because they told us all when we were kids that fish get stuck in them and die…',
embed=Main(
images=[
Image(
alt='A hand holding a plastic rings drink container',
image=<atproto.xrpc_client.models.blob_ref.BlobRef object at 0x168b58890>,
_type='app.bsky.embed.images#image'
)],
_type='app.bsky.embed.images'),
entities=None,
facets=None,
langs=['en'],
reply=None,
_type='app.bsky.feed.post'
),
uri='at://did:plc:xydmw4rhlnb4mrz5eyw3z6ak/app.bsky.feed.post/3jzzabaprgx26',
embed=View(
images=[ViewImage(
alt='A hand holding a plastic rings drink container',
fullsize='https://cdn.bsky.social/imgproxy/LWNCHRKfUz-hYAc5f9xwtL7f7BhzMgtEVdXX8c6EBIY/rs:fit:2000:2000:1:0/plain/bafkreihrnrzbyypa3cmsk2bgruci7hsssjnv3l7dlv5x257utpzg7twcim@jpeg',
thumb='https://cdn.bsky.social/imgproxy/BAD839Z-NtgH_PHGUbkaJOlq2E8KeXJbPfCC8xDVmNY/rs:fit:1000:1000:1:0/plain/bafkreihrnrzbyypa3cmsk2bgruci7hsssjnv3l7dlv5x257utpzg7twcim@jpeg',
_type='app.bsky.embed.images#viewImage'
)],
_type='app.bsky.embed.images#view'
),
labels=[],
likeCount=555,
replyCount=76,
repostCount=42,
viewer=ViewerState(
like=None,
repost=None,
_type='app.bsky.feed.defs#viewerState'
),
_type='app.bsky.feed.defs#postView'),
reason=None,
reply=None,
_type='app.bsky.feed.defs#feedViewPost'
)
You can pick and choose what components from each nested structure you want and then do something similar to what I suggested in the Twitter recipes to save the data locally.