diff --git a/src/lib/api/feed/custom.ts b/src/lib/api/feed/custom.ts
index 75182c41f7..87e45cebab 100644
--- a/src/lib/api/feed/custom.ts
+++ b/src/lib/api/feed/custom.ts
@@ -7,20 +7,25 @@ import {
 
 import {getContentLanguages} from '#/state/preferences/languages'
 import {FeedAPI, FeedAPIResponse} from './types'
+import {createBskyTopicsHeader, isBlueskyOwnedFeed} from './utils'
 
 export class CustomFeedAPI implements FeedAPI {
   getAgent: () => BskyAgent
   params: GetCustomFeed.QueryParams
+  userInterests?: string
 
   constructor({
     getAgent,
     feedParams,
+    userInterests,
   }: {
     getAgent: () => BskyAgent
     feedParams: GetCustomFeed.QueryParams
+    userInterests?: string
   }) {
     this.getAgent = getAgent
     this.params = feedParams
+    this.userInterests = userInterests
   }
 
   async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
@@ -44,6 +49,8 @@ export class CustomFeedAPI implements FeedAPI {
   }): Promise<FeedAPIResponse> {
     const contentLangs = getContentLanguages().join(',')
     const agent = this.getAgent()
+    const isBlueskyOwned = isBlueskyOwnedFeed(this.params.feed)
+
     const res = agent.session
       ? await this.getAgent().app.bsky.feed.getFeed(
           {
@@ -53,6 +60,9 @@ export class CustomFeedAPI implements FeedAPI {
           },
           {
             headers: {
+              ...(isBlueskyOwned
+                ? createBskyTopicsHeader(this.userInterests)
+                : {}),
               'Accept-Language': contentLangs,
             },
           },
diff --git a/src/lib/api/feed/home.ts b/src/lib/api/feed/home.ts
index 4a5308346f..270f3aacb2 100644
--- a/src/lib/api/feed/home.ts
+++ b/src/lib/api/feed/home.ts
@@ -32,14 +32,22 @@ export class HomeFeedAPI implements FeedAPI {
   discover: CustomFeedAPI
   usingDiscover = false
   itemCursor = 0
+  userInterests?: string
 
-  constructor({getAgent}: {getAgent: () => BskyAgent}) {
+  constructor({
+    userInterests,
+    getAgent,
+  }: {
+    userInterests?: string
+    getAgent: () => BskyAgent
+  }) {
     this.getAgent = getAgent
     this.following = new FollowingFeedAPI({getAgent})
     this.discover = new CustomFeedAPI({
       getAgent,
       feedParams: {feed: PROD_DEFAULT_FEED('whats-hot')},
     })
+    this.userInterests = userInterests
   }
 
   reset() {
@@ -47,6 +55,7 @@ export class HomeFeedAPI implements FeedAPI {
     this.discover = new CustomFeedAPI({
       getAgent: this.getAgent,
       feedParams: {feed: PROD_DEFAULT_FEED('whats-hot')},
+      userInterests: this.userInterests,
     })
     this.usingDiscover = false
     this.itemCursor = 0
diff --git a/src/lib/api/feed/merge.ts b/src/lib/api/feed/merge.ts
index c85de0306c..b7ac8bce1c 100644
--- a/src/lib/api/feed/merge.ts
+++ b/src/lib/api/feed/merge.ts
@@ -9,11 +9,13 @@ import {feedUriToHref} from 'lib/strings/url-helpers'
 import {FeedTuner} from '../feed-manip'
 import {FeedTunerFn} from '../feed-manip'
 import {FeedAPI, FeedAPIResponse, ReasonFeedSource} from './types'
+import {createBskyTopicsHeader, isBlueskyOwnedFeed} from './utils'
 
 const REQUEST_WAIT_MS = 500 // 500ms
 const POST_AGE_CUTOFF = 60e3 * 60 * 24 // 24hours
 
 export class MergeFeedAPI implements FeedAPI {
+  userInterests?: string
   getAgent: () => BskyAgent
   params: FeedParams
   feedTuners: FeedTunerFn[]
@@ -27,14 +29,17 @@ export class MergeFeedAPI implements FeedAPI {
     getAgent,
     feedParams,
     feedTuners,
+    userInterests,
   }: {
     getAgent: () => BskyAgent
     feedParams: FeedParams
     feedTuners: FeedTunerFn[]
+    userInterests?: string
   }) {
     this.getAgent = getAgent
     this.params = feedParams
     this.feedTuners = feedTuners
+    this.userInterests = userInterests
     this.following = new MergeFeedSource_Following({
       getAgent: this.getAgent,
       feedTuners: this.feedTuners,
@@ -58,6 +63,7 @@ export class MergeFeedAPI implements FeedAPI {
               getAgent: this.getAgent,
               feedUri,
               feedTuners: this.feedTuners,
+              userInterests: this.userInterests,
             }),
         ),
       )
@@ -254,15 +260,18 @@ class MergeFeedSource_Custom extends MergeFeedSource {
   getAgent: () => BskyAgent
   minDate: Date
   feedUri: string
+  userInterests?: string
 
   constructor({
     getAgent,
     feedUri,
     feedTuners,
+    userInterests,
   }: {
     getAgent: () => BskyAgent
     feedUri: string
     feedTuners: FeedTunerFn[]
+    userInterests?: string
   }) {
     super({
       getAgent,
@@ -270,6 +279,7 @@ class MergeFeedSource_Custom extends MergeFeedSource {
     })
     this.getAgent = getAgent
     this.feedUri = feedUri
+    this.userInterests = userInterests
     this.sourceInfo = {
       $type: 'reasonFeedSource',
       uri: feedUri,
@@ -284,6 +294,7 @@ class MergeFeedSource_Custom extends MergeFeedSource {
   ): Promise<AppBskyFeedGetTimeline.Response> {
     try {
       const contentLangs = getContentLanguages().join(',')
+      const isBlueskyOwned = isBlueskyOwnedFeed(this.feedUri)
       const res = await this.getAgent().app.bsky.feed.getFeed(
         {
           cursor,
@@ -292,6 +303,9 @@ class MergeFeedSource_Custom extends MergeFeedSource {
         },
         {
           headers: {
+            ...(isBlueskyOwned
+              ? createBskyTopicsHeader(this.userInterests)
+              : {}),
             'Accept-Language': contentLangs,
           },
         },
diff --git a/src/lib/api/feed/utils.ts b/src/lib/api/feed/utils.ts
new file mode 100644
index 0000000000..50162ed2a4
--- /dev/null
+++ b/src/lib/api/feed/utils.ts
@@ -0,0 +1,21 @@
+import {AtUri} from '@atproto/api'
+
+import {BSKY_FEED_OWNER_DIDS} from '#/lib/constants'
+import {UsePreferencesQueryResponse} from '#/state/queries/preferences'
+
+export function createBskyTopicsHeader(userInterests?: string) {
+  return {
+    'X-Bsky-Topics': userInterests || '',
+  }
+}
+
+export function aggregateUserInterests(
+  preferences?: UsePreferencesQueryResponse,
+) {
+  return preferences?.interests?.tags?.join(',') || ''
+}
+
+export function isBlueskyOwnedFeed(feedUri: string) {
+  const uri = new AtUri(feedUri)
+  return BSKY_FEED_OWNER_DIDS.includes(uri.host)
+}
diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts
index 747dba02ea..c265cecd60 100644
--- a/src/state/queries/post-feed.ts
+++ b/src/state/queries/post-feed.ts
@@ -15,6 +15,7 @@ import {
 } from '@tanstack/react-query'
 
 import {HomeFeedAPI} from '#/lib/api/feed/home'
+import {aggregateUserInterests} from '#/lib/api/feed/utils'
 import {moderatePost_wrapped as moderatePost} from '#/lib/moderatePost_wrapped'
 import {logger} from '#/logger'
 import {STALE} from '#/state/queries'
@@ -31,7 +32,7 @@ import {FeedTuner, FeedTunerFn, NoopFeedTuner} from 'lib/api/feed-manip'
 import {BSKY_FEED_OWNER_DIDS} from 'lib/constants'
 import {KnownError} from '#/view/com/posts/FeedErrorMessage'
 import {useFeedTuners} from '../preferences/feed-tuners'
-import {useModerationOpts} from './preferences'
+import {useModerationOpts, usePreferencesQuery} from './preferences'
 import {embedViewRecordToPostView, getEmbeddedPost} from './util'
 
 type ActorDid = string
@@ -102,8 +103,11 @@ export function usePostFeedQuery(
 ) {
   const feedTuners = useFeedTuners(feedDesc)
   const moderationOpts = useModerationOpts()
+  const {data: preferences} = usePreferencesQuery()
+  const enabled =
+    opts?.enabled !== false && Boolean(moderationOpts) && Boolean(preferences)
+  const userInterests = aggregateUserInterests(preferences)
   const {getAgent} = useAgent()
-  const enabled = opts?.enabled !== false && Boolean(moderationOpts)
   const lastRun = useRef<{
     data: InfiniteData<FeedPageUnselected>
     args: typeof selectArgs
@@ -141,6 +145,7 @@ export function usePostFeedQuery(
               feedDesc,
               feedParams: params || {},
               feedTuners,
+              userInterests, // Not in the query key because they don't change.
               getAgent,
             }),
             cursor: undefined,
@@ -371,11 +376,13 @@ function createApi({
   feedDesc,
   feedParams,
   feedTuners,
+  userInterests,
   getAgent,
 }: {
   feedDesc: FeedDescriptor
   feedParams: FeedParams
   feedTuners: FeedTunerFn[]
+  userInterests?: string
   getAgent: () => BskyAgent
 }) {
   if (feedDesc === 'home') {
@@ -384,9 +391,10 @@ function createApi({
         getAgent,
         feedParams,
         feedTuners,
+        userInterests,
       })
     } else {
-      return new HomeFeedAPI({getAgent})
+      return new HomeFeedAPI({getAgent, userInterests})
     }
   } else if (feedDesc === 'following') {
     return new FollowingFeedAPI({getAgent})
@@ -401,6 +409,7 @@ function createApi({
     return new CustomFeedAPI({
       getAgent,
       feedParams: {feed},
+      userInterests,
     })
   } else if (feedDesc.startsWith('list')) {
     const [_, list] = feedDesc.split('|')
diff --git a/src/state/queries/suggested-follows.ts b/src/state/queries/suggested-follows.ts
index 936912ab34..3338130f4a 100644
--- a/src/state/queries/suggested-follows.ts
+++ b/src/state/queries/suggested-follows.ts
@@ -12,8 +12,16 @@ import {
   useQuery,
 } from '@tanstack/react-query'
 
+import {
+  aggregateUserInterests,
+  createBskyTopicsHeader,
+} from '#/lib/api/feed/utils'
+import {getContentLanguages} from '#/state/preferences/languages'
 import {STALE} from '#/state/queries'
-import {useModerationOpts} from '#/state/queries/preferences'
+import {
+  useModerationOpts,
+  usePreferencesQuery,
+} from '#/state/queries/preferences'
 import {useAgent, useSession} from '#/state/session'
 
 const suggestedFollowsQueryKeyRoot = 'suggested-follows'
@@ -29,6 +37,7 @@ export function useSuggestedFollowsQuery() {
   const {currentAccount} = useSession()
   const {getAgent} = useAgent()
   const moderationOpts = useModerationOpts()
+  const {data: preferences} = usePreferencesQuery()
 
   return useInfiniteQuery<
     AppBskyActorGetSuggestions.OutputSchema,
@@ -37,14 +46,23 @@ export function useSuggestedFollowsQuery() {
     QueryKey,
     string | undefined
   >({
-    enabled: !!moderationOpts,
+    enabled: !!moderationOpts && !!preferences,
     staleTime: STALE.HOURS.ONE,
     queryKey: suggestedFollowsQueryKey,
     queryFn: async ({pageParam}) => {
-      const res = await getAgent().app.bsky.actor.getSuggestions({
-        limit: 25,
-        cursor: pageParam,
-      })
+      const contentLangs = getContentLanguages().join(',')
+      const res = await getAgent().app.bsky.actor.getSuggestions(
+        {
+          limit: 25,
+          cursor: pageParam,
+        },
+        {
+          headers: {
+            ...createBskyTopicsHeader(aggregateUserInterests(preferences)),
+            'Accept-Language': contentLangs,
+          },
+        },
+      )
 
       res.data.actors = res.data.actors
         .filter(