---
title: "Wrangler"
description: "Learn how to instrument a Cloudflare Worker built with Wrangler, using the withSentry wrapper."
url: https://docs.sentry.io/platforms/javascript/guides/cloudflare/install/wrangler/
---

# Installation Methods Wrangler for Cloudflare

We recommend building your Worker with Vite and the [Sentry Vite plugin](https://docs.sentry.io/platforms/javascript/guides/cloudflare/install/vite-plugin.md). It wraps your entry for you and is the only way to trace bundled dependencies in the Workers runtime. To move an existing Wrangler project over, see [Migrating From Wrangler](https://docs.sentry.io/platforms/javascript/guides/cloudflare/install/vite-plugin.md#migrating-from-wrangler).

If you deploy with `wrangler` directly rather than building with Vite, wrap your Worker entry manually with `Sentry.withSentry()`.

Everything else is the same: install, Wrangler configuration, source maps, and the options reference all carry over from the quick start.

## [What You Give Up](https://docs.sentry.io/platforms/javascript/guides/cloudflare/install/wrangler.md#what-you-give-up)

`withSentry` gives you the same errors and request traces as the plugin. What a plain Wrangler build can't do is instrument your bundled dependencies.

The Workers runtime doesn't let the SDK patch modules at runtime, so packages like database and AI clients are only traced when something rewrites them during the build. That's what the Vite plugin's `buildTimeInstrumentation` does. Without it, spans from those packages are missing, and you only get the spans the SDK creates itself.

You also have to keep the wrapper in your code, and list your RPC trace propagation bindings by hand, because a plain build can't derive them. See [RPC Trace Propagation](https://docs.sentry.io/platforms/javascript/guides/cloudflare/tracing/distributed-tracing.md#rpc-trace-propagation).

## [Configure](https://docs.sentry.io/platforms/javascript/guides/cloudflare/install/wrangler.md#configure)

Wrap your exported handler with `Sentry.withSentry()` to start capturing errors and traces from your Worker:

```typescript
import * as Sentry from "@sentry/cloudflare";

export default Sentry.withSentry(
  (env: Env) => ({
    dsn: "https://<key>@o<orgId>.ingest.sentry.io/<projectId>",

    // Set tracesSampleRate to 1.0 to capture 100% of spans for tracing.
    // Learn more at
    // https://docs.sentry.io/platforms/javascript/guides/cloudflare/configuration/options/#tracesSampleRate
    tracesSampleRate: 1.0,
  }),
  {
    async fetch(request, env, ctx) {
      // Your worker logic here
      return new Response("Hello World!");
    },
  },
);
```

## [Instrument Durable Objects, Workflows, and Agents](https://docs.sentry.io/platforms/javascript/guides/cloudflare/install/wrangler.md#instrument-durable-objects-workflows-and-agents)

Durable Objects, Workflows, and Agents SDK classes each need their own wrapper: `instrumentDurableObjectWithSentry`, `instrumentWorkflowWithSentry`, and `instrumentAgentWithSentry`. Each wrapper takes an options callback like `withSentry` does. Define the callback once to share it, and export each wrapped class under the name that your wrangler config uses:

```typescript
import * as Sentry from "@sentry/cloudflare";
import { DurableObject, WorkflowEntrypoint } from "cloudflare:workers";
// Only needed if you use the Agents SDK
import { Agent } from "agents";

const sentryOptions = (env: Env) => ({
  dsn: "https://<key>@o<orgId>.ingest.sentry.io/<projectId>",
  tracesSampleRate: 1.0,
  // Bindings that carry the trace over RPC. An empty list lets a class
  // receive traces over RPC without propagating them to other bindings.
  rpcTracePropagationBindings: [],
});

class MyDurableObjectBase extends DurableObject<Env> {
  // ...
}

class MyWorkflowBase extends WorkflowEntrypoint<Env> {
  // ...
}

class MyAgentBase extends Agent<Env> {
  // ...
}

export const MyDurableObject = Sentry.instrumentDurableObjectWithSentry(
  sentryOptions,
  MyDurableObjectBase,
);

export const MyWorkflow = Sentry.instrumentWorkflowWithSentry(
  sentryOptions,
  MyWorkflowBase,
);

export const MyAgent = Sentry.instrumentAgentWithSentry(
  sentryOptions,
  MyAgentBase,
);
```

`instrumentAgentWithSentry` works with `Agent` from `agents`, `AIChatAgent` from `@cloudflare/ai-chat`, and `McpAgent` from `agents/mcp`, and requires SDK version 10.69.0 or higher. For what each wrapper captures, see [Durable Objects](https://docs.sentry.io/platforms/javascript/guides/cloudflare/features/durableobject.md), [Workflows](https://docs.sentry.io/platforms/javascript/guides/cloudflare/features/workflows.md), and [Agents SDK](https://docs.sentry.io/platforms/javascript/guides/cloudflare/agent-tracing/agents-sdk.md). To connect traces across RPC calls, list your bindings as shown in [RPC Trace Propagation](https://docs.sentry.io/platforms/javascript/guides/cloudflare/tracing/distributed-tracing.md#rpc-trace-propagation).

## [Control the Data You Send to Sentry (Optional)](https://docs.sentry.io/platforms/javascript/guides/cloudflare/install/wrangler.md#control-the-data-you-send-to-sentry-optional)

By default, the SDK sends user identity data (IP address, ID, and similar) and other data like HTTP bodies and URL query parameters. The SDK always filters sensitive values whose keys match a built-in denylist, such as `auth` or `password`, and sends `[Filtered]` instead.

To send less data, turn off the categories you don't need in the `dataCollection` option:

```typescript
export default Sentry.withSentry(
  (env: Env) => ({
    dsn: "https://<key>@o<orgId>.ingest.sentry.io/<projectId>",
    dataCollection: {
      userInfo: false,
      // other categories
    },
  }),
  handler,
);
```

For the full list of categories and their defaults, see the [`dataCollection` options](https://docs.sentry.io/platforms/javascript/guides/cloudflare/configuration/options.md#dataCollection).

## [Verify Your Setup](https://docs.sentry.io/platforms/javascript/guides/cloudflare/install/wrangler.md#verify-your-setup)

Add a `/debug-sentry` route to your Worker that throws when called:

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

export default Sentry.withSentry(
  (env) => ({
    dsn: "https://<key>@o<orgId>.ingest.sentry.io/<projectId>",
  }),
  {
    async fetch(request) {
      const url = new URL(request.url);

      if (url.pathname === "/debug-sentry") {
        throw new Error("My first Sentry error!");
      }

      // Your existing routes and logic here...
      return new Response("...");
    },
  },
);
```

Then head over to your project on [Sentry.io](https://sentry.io) to view the collected data (it takes a couple of moments for the data to appear).
