---
title: "Profiling"
description: "Collect & view performance insights for JavaScript programs with Sentry's Profiling integrations. Get started with profiling to understand your application's performance."
url: https://docs.sentry.io/platforms/javascript/profiling/
---

# Set Up Profiling | Sentry for JavaScript

Browser Profiling is currently in beta. Beta features are still in progress and may have bugs. We recognize the irony.

[Profiling](https://docs.sentry.io/product/explore/profiling.md) captures function-level data from your production code to enable you to fine-tune your app's performance. It tracks what's being called, how often, and where. In the browser, this helps you pinpoint causes of UI jank, understand why metrics like [Interaction to Next Paint (INP)](https://docs.sentry.io/product/insights/web-vitals/web-vitals-concepts.md#interaction-to-next-paint-inp) are slow, or identify long tasks blocking repaints and causing frame drops.

##### Chromium Only

Browser Profiling uses the [JS Self-Profiling API](https://wicg.github.io/js-self-profiling/), currently only available in Chromium-based browsers (Chrome, Edge). Profiles will only include data from these browsers.

## [Quick Setup](https://docs.sentry.io/platforms/javascript/profiling.md#quick-setup)

**Requirements**: `@sentry/browser `SDK version `10.27.0`+ (or `7.60.0`+ for deprecated transaction-based profiling)

### [1. Install the SDK](https://docs.sentry.io/platforms/javascript/profiling.md#1-install-the-sdk)

```bash
npm install @sentry/browser --save
```

### [2. Add the Document-Policy Header](https://docs.sentry.io/platforms/javascript/profiling.md#2-add-the-document-policy-header)

Your server must return `Document-Policy: js-profiling` in response headers.

How you configure this depends on your hosting platform or server. Select your setup below:

Vercel

Add to `vercel.json`:

`vercel.json`

```json
{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "Document-Policy",
          "value": "js-profiling"
        }
      ]
    }
  ]
}
```

Netlify

Add to `netlify.toml`:

`netlify.toml`

```toml
[[headers]]
  for = "/*"
  [headers.values]
    Document-Policy = "js-profiling"
```

Or add to `_headers` file in your publish directory:

`_headers`

```text
/*
  Document-Policy: js-profiling
```

Express / Node.js

Use middleware to set the header:

`server.js`

```javascript
app.use((req, res, next) => {
  res.set("Document-Policy", "js-profiling");
  next();
});

// Or for a specific route
app.get("/", (req, res) => {
  res.set("Document-Policy", "js-profiling");
  res.sendFile("index.html");
});
```

Nginx

Add to your server or location block:

`nginx.conf`

```nginx
server {
    location / {
        add_header Document-Policy "js-profiling";
        # ... rest of your config
    }
}
```

Apache

Add to `.htaccess` or your server config:

`.htaccess`

```apache
<IfModule mod_headers.c>
    Header set Document-Policy "js-profiling"
</IfModule>
```

AWS CloudFront

Use a CloudFront Response Headers Policy or a CloudFront Function:

`cloudfront-function.js`

```javascript
function handler(event) {
  var response = event.response;
  var headers = response.headers;
  headers["document-policy"] = { value: "js-profiling" };
  return response;
}
```

Attach this function as a "Viewer Response" function to your CloudFront distribution.

ASP.NET Core

Add middleware to set the header:

`Program.cs`

```csharp
app.Use(async (context, next) => {
    context.Response.OnStarting(() => {
        context.Response.Headers.Append("Document-Policy", "js-profiling");
        return Task.CompletedTask;
    });
    await next();
});
```

##### Can't modify server headers?

If you're using a hosting provider that doesn't allow custom response headers (some static hosting services, corporate proxies, etc.), browser profiling won't be available for your application. Consider using Sentry's [backend profiling](https://docs.sentry.io/product/explore/profiling.md) for your server-side code instead.

### [3. Configure the SDK](https://docs.sentry.io/platforms/javascript/profiling.md#3-configure-the-sdk)

```javascript
import * as Sentry from "@sentry/browser";

Sentry.init({
  dsn: "___PUBLIC_DSN___",
  integrations: [
    // Add browser profiling integration to the list of integrations
    Sentry.browserTracingIntegration(),
    Sentry.browserProfilingIntegration(),
  ],

  // Set tracesSampleRate to 1.0 to capture 100%
  // of transactions for tracing.
  // We recommend adjusting this value in production
  tracesSampleRate: 1.0,
  // Set `tracePropagationTargets` to control for which URLs trace propagation should be enabled
  tracePropagationTargets: ["localhost", /^https:\/\/yourserver\.io\/api/],

  // Set profileSessionSampleRate to 1.0 to profile during every session.
  // The decision, whether to profile or not, is made once per session (when the SDK is initialized).
  profileSessionSampleRate: 1.0,
});
```

## [Profiling Modes](https://docs.sentry.io/platforms/javascript/profiling.md#profiling-modes)

| Mode                 | Description                                   | Use When                                            |
| -------------------- | --------------------------------------------- | --------------------------------------------------- |
| **Manual** (default) | You control when profiling runs               | Profiling specific user flows or interactions       |
| **Trace**            | Profiler runs automatically with active spans | You want profiles attached to all traced operations |

### [Manual Mode](https://docs.sentry.io/platforms/javascript/profiling.md#manual-mode)

Start and stop the profiler around code you want to profile:

```javascript
Sentry.uiProfiler.startProfiler();
// Code here will be profiled
Sentry.uiProfiler.stopProfiler();
```

### [Trace Mode](https://docs.sentry.io/platforms/javascript/profiling.md#trace-mode)

Profiles automatically attach to spans. Enable by setting `profileLifecycle: "trace"`:

```javascript
Sentry.init({
  dsn: "___PUBLIC_DSN___",
  integrations: [
    Sentry.browserTracingIntegration(),
    Sentry.browserProfilingIntegration(),
  ],
  tracesSampleRate: 1.0,
  profileSessionSampleRate: 1.0,
  profileLifecycle: "trace",
});
```

## [Sentry vs Chrome DevTools](https://docs.sentry.io/platforms/javascript/profiling.md#sentry-vs-chrome-devtools)

|                   | Sentry Profiling            | Chrome DevTools     |
| ----------------- | --------------------------- | ------------------- |
| **Environment**   | Production (real users)     | Local development   |
| **Sampling rate** | 100Hz (10ms period)         | 1000Hz (1ms period) |
| **Source maps**   | Deobfuscated function names | Minified names      |
| **Data scope**    | Aggregated across users     | Single session      |

Troubleshooting

**Chrome DevTools shows "Profiling Overhead"**

When `browserProfilingIntegration` is enabled, Chrome DevTools incorrectly attributes rendering work as profiling overhead. Disable the integration when using DevTools locally.

**Profiles only from Chrome users**

This is expected. The JS Self-Profiling API is currently only implemented in Chromium browsers. Consider this bias when analyzing data.
