Get to know MDN better
Deprecated: This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using it, and update existing code if possible; see the compatibility table at the bottom of this page to guide your decision. Be aware that this feature may cease to work at any time.
Non-standard: This feature is not standardized. We do not recommend using non-standard features in production, as they have limited browser support, and may change or be removed. However, they can be a suitable alternative in specific cases where no standard option exists.
Warning: This feature is currently opposed by two browser vendors. See the Standards positions section for details of opposition.
Note: An Enrollment process is required to use the Topics API in your applications. See the Enrollment section for details of what sub-features are gated by enrollment.
This page explains how the Topics API works and how it can be used to create an interest-based advertising (IBA) solution.
Let's say we've got an ad tech platform, ad-tech1.example, which is embedding ads via <iframe>s into the following publisher sites:
If the <iframe> content from ad-tech1.example implements a feature that enables the Topics API, when each of the sites is loaded the browser will:
Note: Different browser implementations may select topics in different ways. The below text is based on how Chrome currently selects topics, for demonstration purposes.
On an ongoing basis, the browser will:
Keep track of how often the user observes each topic during each new epoch. An epoch is a week by default, but the length can be altered for testing purposes (see Testing hints).
Chrome places each of the 22 root topics (those without an ancestor) from the taxonomy into one of two buckets indicating higher or standard utility for the overall ad tech ecosystem. All descendants of the root topics inherit the same bucket assignment from their parent. The assignment of root topics to buckets is based on input about utility Google received from companies across the ecosystem.
Select top topics for each user, at the end of each epoch:
The top topics are returned to ad-tech1.example, only if ad-tech1.example appears in the list of caller domains for each topic, as stored in the topic's history entry.
Note: Initially, no topics are returned, so the <iframe> will likely display a default non-targeted ad. However, once the end of the first epoch is reached, the API will start to return topics and ad-tech1.example can start to show more relevant ads based on the observed topics for the current user.
ad-tech1.example then selects a relevant ad to serve to the user, based on the returned topics.
The following features all serve a dual purpose — they return the user's top topics to the caller and they trigger the browser to record the current page visit as observed by the caller, so the page's hostname can later be used in topics calculation. To do so, they need to be included in a calling ad tech's <iframe>; the <iframe> then has to be embedded on the pages where you want topics observed.
You can specify a browsingTopics: true option in the options object of a fetch() call to the ad tech platform.
You could also pass browsingTopics: true into the options object of a Request() constructor call, and pass the resulting Request object into the fetch() call.
You can set a browsingtopics attribute on the <iframe>, at the same time or before setting the src attribute to load the source. This could be done:
When the request associated with one of the above features is sent:
A Sec-Browsing-Topics header is sent along with the request, which contains the top topic(s) for the current user.
The ad tech server selects a relevant ad to display in the <iframe>, based on these topics, and sends the required data to display it in the response.
An Observe-Browsing-Topics header should be set on the response to the request — this has the effect of causing the browser to record the current page visit as observed by the calling ad tech provider, so the associated topic(s) will be recorded in a topics history entry, and subsequently be used in topic selection.
Note: It is important to clarify that this doesn't record the top topics sent in the Sec-Browsing-Topics header as observed. It records the topics inferred from the calling site's URL (i.e., the site where the ad tech <iframe> is embedded) as observed.
Alternatively, the embedded <iframe> can call Document.browsingTopics() to return a user's current top topic(s), which can then be returned to the ad tech platform in a subsequent fetch request. This does not rely on the HTTP headers, but is somewhat less performant. You are advised to use one of the HTTP header methods listed above, falling back to browsingTopics() only in situations where the headers cannot be modified.
Note: Because the browsingTopics() method does not rely on the HTTP headers, the Observe-Browsing-Topics header is not used for setting the topics as observed and recording/updating topics history entries; the browser does this automatically when the method is called.
A caller can only access topics that they themselves have observed for a user — and not topics observed by other callers. For example:
These ad tech platforms will only get topics for a user that they have observed. In this example, ad-tech1.example won't get "Gardening" and ad-tech2.example won't get "Tennis".
In other words, callers such as ad tech platforms only get topics for pages where they have a presence. More importantly, the recorded topics of interest are the only information that can be accessed via this API — unlike with tracking cookies, no other information can be leaked.
The default epoch length for observing topics is one week, which is way too long to test code that uses the Topics API. To shorten this for test purposes, in Chrome you can open the browser with a feature flag along the following lines:
See Run Chromium with command-line switches for more information on how to do this.
You can also test your Topics API code locally without enrollment by enabling the following Chrome developer flag:
chrome://flags/#privacy-sandbox-enrollment-overrides
This page was last modified on Dec 15, 2025 by MDN contributors.
Your blueprint for a better internet.
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998–2026 by individual mozilla.org contributors. Content available under a Creative Commons license.