---
title: Script tag attributes
description: Reference for the c15t script tag on plain HTML pages, covering the
  bundle files, every data attribute on the script tag, the DevTools tag and
  your own markup, and the modes the attributes select.
group: frameworks
lastModified: "2026-10-10T16:01:45+01:00"
---
## Where each part is documented

|Reference|Page|
|--|--|
|Bundle files and every `data-*` attribute|This page|
|`window.c15t` methods and the call queue|[window.c15t API](/docs/frameworks/html/api)|
|Options for `c15t.push(['config', …])`|[Configuration](/docs/frameworks/html/configuration)|
|Events, `c15t:*` DOM events and callbacks|[Events and callbacks](/docs/frameworks/html/callbacks)|

## Script files

`@c15t/browser` publishes browser bundles. Inth and a self-hosted c15t
backend serve `c15t.js`, `c15t.headless.js` and `c15t.iab.js` from the
backend's URL, such as `https://your-project.inth.app/c15t.js`, with the
backend URL already configured. Headless and IAB routes also inline the
policy manifest. Load a file from
`https://cdn.jsdelivr.net/npm/@c15t/browser@<version>/dist/<file>`, or the
same path on unpkg, when no backend serves it, such as `c15t.devtools.js` or
`c15t.offline.js`.

|File|What it contains|
|--|--|
|`c15t.js`|The default stock UI and client for hosted mode. Excludes offline policy presets, offline resolution and manifest transport code. Requires a backend URL or a queued hosted factory.|
|`c15t.offline.js`|The stock UI and client for offline mode only. Includes policy presets and excludes hosted and manifest transport code.|
|`c15t.headless.js`|The same runtime and `window.c15t` API with no banner, dialog or CSS. Your page renders the UI. See [headless](/docs/frameworks/html/headless).|
|`c15t.iab.js`|Replaces `c15t.js` when your policy uses IAB TCF. See [IAB TCF](/docs/frameworks/html/iab).|
|`c15t.devtools.js`|The DevTools panel, loaded as a second tag. See [DevTools](/docs/frameworks/html/dev-tools).|

Load one of `c15t.js`, `c15t.offline.js`, `c15t.headless.js` or
`c15t.iab.js` on a page, never two. `c15t.iab.js` throws an error if another one loaded first. When
`c15t.js`, `c15t.offline.js` or `c15t.headless.js` finds another c15t bundle
already installed, it leaves the first one in place and does not start a
second client.

`dist/c15t.css` and `dist/c15t.iab.css` are the stylesheets, for pages that
render the UI with `data-shadow="false"` and load the CSS themselves.

## Script tag attributes

The tag reads attributes once, when the script runs. The default `c15t.js`
bundle uses hosted mode and requires `data-backend-url` unless a queued
`config` supplies a backend URL or hosted factory.

`c15t.js` rejects offline or manifest mode, manifest options and
`data-policy-rules`, because the attribute contains preset names. Authored
`PolicyRule` objects can be passed in a queued `config` instead.
`c15t.offline.js` rejects backend URLs, manifest options and modes other
than offline. The headless and IAB bundles also accept manifest and custom
transports. Every bundle keeps the call queue, `data-manual` and the page
hooks described below.

|Attribute|What it does|
|--|--|
|`data-backend-url`|Your Inth or self-hosted backend URL. Selects hosted mode.|
|`data-mode`|Optional `hosted` for `c15t.js` or `offline` for `c15t.offline.js`. Headless and IAB also accept `manifest`; without it, they pick `manifest` when a manifest URL is set, `hosted` when a backend URL is set, and `offline` otherwise. Headless and IAB ignore unknown values; hosted and offline reject them.|
|`data-manifest-url`|Where headless or IAB fetches the policy manifest in manifest mode. See [choose a mode](#choose-a-mode).|
|`data-policy-rules`|Comma-separated policy presets for offline mode, such as `europeOptIn,usPrivacyStatesOptOut,worldNone`. Any name exported by `policyRulePresets` works; an unknown name throws. [Policies](/docs/concepts/policies) describes the presets.|
|`data-categories`|Comma-separated categories to offer in the preference dialog, such as `measurement,marketing`. Without it, the dialog offers the categories your gated scripts, iframes and rules use. This changes the dialog, not the policy.|
|`data-country`, `data-region`|The visitor's location, when your host can print it into the page. Policy matching uses these instead of detection.|
|`data-language`|Use this language instead of the browser's. See [translations](/docs/frameworks/html/translations).|
|`data-privacy-policy-url`, `data-cookie-policy-url`, `data-terms-url`|Show these legal links in the banner and the preference dialog.|
|`data-color-scheme`|`light`, `dark` or `system`. Defaults to `system`.|
|`data-trigger`|Show the [floating trigger](/docs/frameworks/html/components/trigger) that reopens the preference dialog.|
|`data-hide-branding`|Hide the "Secured by" tag in the banner and dialog. The IAB banner always keeps it.|
|`data-shadow="false"`|Render the UI into the page instead of a shadow root, so your stylesheet applies. See [customize](/docs/frameworks/html/customize#style-it-with-your-own-stylesheet).|
|`data-no-ui`|Start the runtime without the stock UI. `c15t.js` still downloads the UI code and CSS; load `c15t.headless.js` to skip them. The UI attributes above are ignored.|
|`data-manual`|Do not start. Your page calls `c15t.init()` later. See [start c15t yourself](/docs/frameworks/html/api#start-c15t-yourself).|
|`data-nonce`|The Content Security Policy nonce for the stock UI's `<style>` element and the scripts c15t loads. Without it, c15t uses the tag's own `nonce` attribute. See [Content Security Policy](/docs/frameworks/html/content-security-policy).|

Flag attributes such as `data-trigger` are on when present, unless their value
is `false`. `data-shadow` is the exception. Only `data-shadow="false"` changes
anything. `data-backend` is accepted as an older spelling of
`data-backend-url`.

Everything the attributes set, and every option they cannot express, can also
be passed in a queued `config` call. See
[configuration](/docs/frameworks/html/configuration).

## DevTools tag attributes

These go on the `c15t.devtools.js` tag:

|Attribute|What it does|
|--|--|
|`data-open`|Open the panel on load. `data-open="false"` keeps it closed.|
|`data-tab`|The first tab: `consents`, `scripts`, `location`, `policy`, `iab`, `events` or `actions`.|
|`data-position`|The corner: `bottom-right`, `bottom-left`, `top-right` or `top-left`.|

## Attributes on your own markup

These work anywhere on the page, including markup added after load:

|Markup|What it does|Page|
|--|--|--|
|`data-c15t-action="accept"`, `"reject"`, `"customize"`, `"dismiss"`, `"banner"` or `"close"`|Runs the action on click.|[Action buttons](/docs/frameworks/html/components/action-buttons)|
|A link whose `href` ends in `#c15t-preferences`|Opens the preference dialog on click.|[Preferences link](/docs/frameworks/html/components/preferences-link)|
|`<script type="text/plain" data-c15t-category="…">`|Runs the script once that category is allowed. `data-c15t-vendor` adds a vendor gate.|[Gated scripts](/docs/frameworks/html/components/gated-script)|
|`<iframe data-src="…" data-category="…">`|Sets the iframe's `src` once that category is allowed. `data-vendor` adds a vendor gate.|[Embeds](/docs/frameworks/html/embeds)|

c15t sets these attributes itself. Read them in CSS or tests, but do not
write them:

|Attribute|Where|Meaning|
|--|--|--|
|`data-c15t-activated`|Gated `<script>`|`true` once the tag ran, `invalid` when its category is unknown, `untrusted` when the page has a nonce and the tag lacks it.|
|`data-c15t-paused`|Gated `<iframe>`|c15t removed a `src` the iframe already had.|
|`data-c15t-ui`|The UI host `<div>`|The element that holds the banner, dialog and trigger.|
|`data-testid`|Parts of the stock UI|Stable names for styling and tests. Each component page lists them.|

## Choose a mode

|Mode|Set it with|What happens|
|--|--|--|
|Hosted|`c15t.js` with `data-backend-url`|Each fresh visit asks the backend's `/init` endpoint for the visitor's policy. Choices are saved to the backend.|
|Manifest|`c15t.headless.js` or `c15t.iab.js` with `data-manifest-url`, or `mode: 'manifest'` with an inline `manifest` in `config`|The browser resolves the policy from the backend's public, cacheable `/manifest`. Choices still go to the backend.|
|Offline|`c15t.offline.js` with no backend URL|Policy rules come from `data-policy-rules` or c15t's recommended rules. Choices stay in the browser. Not recommended for production environments.|

A tag loaded from a backend's `/c15t.js`, such as
`https://your-project.inth.app/c15t.js`, starts in hosted mode with the
backend URL already configured, so it needs no `data-backend-url`.

In manifest mode, c15t can take the backend URL from a manifest URL that ends
in `/manifest`. A manifest on another host, or an inline manifest, also needs
`data-backend-url` so saves have somewhere to go. When a policy depends on the
visitor's location and the page does not supply it, c15t falls back to the
backend's `/init`. [Data fetching](/docs/concepts/data-fetching) compares the
modes.

Use the default `c15t.js` for hosted mode and `c15t.offline.js` for offline
mode. For manifest mode or custom transports with the stock UI, use the
`@c15t/browser` ES module. The headless script supports those modes with your
own UI, and the IAB script supports them for IAB policies. Loading `c15t.js`
without a backend URL throws unless a hosted factory is supplied.

Offline mode cannot see the visitor's country. Without `data-country`, every
visitor gets the strict opt-in fallback.
