---
title: DevTools
description: Add the c15t DevTools panel to a plain HTML page with a second
  script tag to inspect consent, gated scripts, the resolved policy and events,
  and to test other countries.
group: frameworks
lastModified: "2026-10-10T16:01:45+01:00"
---
## Add the panel

Add the DevTools tag next to the c15t tag while you debug:

```html
<script
  src="https://cdn.jsdelivr.net/npm/@c15t/browser@alpha/dist/c15t.devtools.js"
  data-open
  data-tab="location"
  defer
></script>
```

Tag order does not matter. Loaded first, the DevTools tag queues itself on
`window.c15t` and mounts once the client starts. Loaded after, it mounts at
once. With `data-manual` on the c15t tag, it waits for `c15t.init()`.

|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`. An unknown value is ignored.|
|`data-position`|The corner: `bottom-right`, `bottom-left`, `top-right` or `top-left`.|

The panel renders in its own shadow root, so your theme's CSS does not change
it.

## Open DevTools from the trigger

With `data-trigger` on the c15t tag, the trigger shows a DevTools button next
to its own while the panel is mounted, and the panel hides its floating
launcher, so one control sits in the corner. The DevTools button sits at the
end farthest from the corner. The panel opens just past the trigger, aligned
with its outer edge, and follows it when you drag the trigger to another
corner.

The trigger hides while the banner or the dialog is open. The panel then shows
its own launcher in the `data-position` corner until the trigger returns. With
`c15t.headless.js` there is no trigger, so the panel always keeps its launcher.

## What each tab shows

|Tab|Shows|
|--|--|
|Consents|Each category's current permission, with switches and **Save changes**, **Accept all** and **Reject optional** buttons. Those buttons record a real choice.|
|Scripts|Scripts from `config` and their state: blocked, loading, loaded, failed or retained. A page scan lists other script and iframe elements.|
|Location|The country, region, language and GPC signal. **Apply and refresh** resolves the policy again with your values; **Clear overrides** goes back to detection.|
|Policy|The resolved policy rule and the prompt it requires.|
|IAB|Purposes, vendors and the TC string, under an IAB policy with `c15t.iab.js`.|
|Events|Every consent event in order.|
|Actions|**Show banner**, **Open preferences** and **Clear stored records**.|

The page scan in the Scripts tab lists what is in the DOM. It is not proof
that a request was sent or held back; check the Network tab for that.

## Use it from the console

Once mounted, the panel is `c15t.devtools` in the console. Call
`c15t.devtools.destroy()` to remove it. `c15t.dispose()` removes it too.

## Test another country

A policy that depends on location shows different banners around the world.
Open the Location tab, set the country to `DE`, or `US` with region `CA`, and
click **Apply and refresh**. The banner follows the policy for that location,
without a VPN. The override lasts until you reload.

## Keep it out of production

The panel shows internal consent state to anyone who opens the page. Remove
the tag before you publish, or print it only in a staging template. It also
adds a `<style>` element, which a strict [Content Security Policy](/docs/frameworks/html/content-security-policy)
blocks.

## Check it works

1. Add the tag and reload. The panel opens on the tab you chose.
2. Click **Accept All** in the banner. The Events tab lists the save, and
   the Consents tab shows each category allowed.
3. Remove the tag and reload. No panel appears and `c15t.devtools` is `null`.
