---
title: Get started with Browser SDK 2
description: "Install Amplitude Browser SDK 2, initialize it, send a first event, and fix the browser-specific problems that stop events from arriving."
product: analytics
lang: en
last_updated: 2026-10-28
token_estimate: 2481
---
# Get started with Browser SDK 2

> For AI agents: a documentation index is available at [/docs/llms.txt](/docs/llms.txt). Append `.md` to any page URL for markdown, or send `Accept: text/markdown`.

- **Package:** `@amplitude/analytics-browser` ([npm](https://www.npmjs.com/package/@amplitude/analytics-browser))
- **Latest version:** 2.48.1

This guide helps you install Browser SDK 2 (`@amplitude/analytics-browser`), initialize it, and send one custom event to Amplitude. Each step lists the browser conditions that commonly break that step, so you can fix a problem where it happens. For the full option list, go to [Configuration options](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2/reference#configuration-options).

Browser SDK 2 is the analytics-only package. If you also need Session Replay, Feature Experiment, or Guides and Surveys, install the [Browser Unified SDK](https://amplitude.com/docs/sdks/analytics/browser/browser-unified-sdk) (`@amplitude/unified`) instead. It includes Browser SDK 2, so don't install both packages on the same page.

## Prerequisites

- An Amplitude project and its API key. Find the key in **Settings > Projects > _your project_ > General**.
- The data center your organization uses: US (default) or EU.
- The latest Browser SDK 2 release, or a pinned version you check against the [Browser SDK 2 release notes](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2-release-notes) for the features you use.
- A page served over `http://` or `https://`. Pages opened from `file://` can't set cookies, so the SDK can't persist identity between loads.

## Install the SDK

Choose one installation method. Use npm or yarn if you bundle your JavaScript. Use the script loader if you add tags to HTML directly or through a tag manager.

#### npm

```bash
npm install @amplitude/analytics-browser
```

```ts
import * as amplitude from "@amplitude/analytics-browser";
```

#### yarn

```bash
yarn add @amplitude/analytics-browser
```

```ts
import * as amplitude from "@amplitude/analytics-browser";
```

#### Script loader

Paste this snippet into the `<head>` of every page. It defines a global `amplitude` object that queues calls until the full SDK downloads, so you can call `amplitude.init()` right after the snippet.

To use the Unified SDK instead, install `@amplitude/unified` with `npm install @amplitude/unified` or `yarn add @amplitude/unified`, and import it the same way:

```ts
import * as amplitude from "@amplitude/unified";
```

The Unified package exports the same tracking and identity methods, such as `track()` and `setUserId()`, but not `init()`. Call `initAll()` instead, and pass the analytics options from this guide under `analytics`:

```ts
amplitude.initAll("YOUR_API_KEY", {
  serverZone: "EU", // Omit for US projects.
  analytics: { autocapture: true },
});
```

`initAll()` doesn't accept a user ID argument. Call `setUserId()` after it.

### Fix installation problems

| Symptom | Cause | Fix |
| --- | --- | --- |
| `amplitude is not defined` in the console (script loader) | The snippet loads after your code runs, or a Content Security Policy blocks it. | Place the snippet before any code that calls `amplitude`. Add `https://*.amplitude.com` to `script-src`. |
| `net::ERR_BLOCKED_BY_CLIENT` for the SDK script | An ad blocker or privacy extension blocks the CDN. | Install from npm and bundle the SDK with your code, or test in a profile without extensions. |
| Two `amplitude` globals, or events sent twice | The page loads both this snippet and the Unified Script or `@amplitude/unified`. | Keep one Amplitude entry point per page. |

## Initialize the SDK

Call `init()` once, as early as your app has the context it needs, such as a known user ID. Calls you make before `init()` finishes wait in a queue and run in order after it completes.

```ts
amplitude.init("YOUR_API_KEY", {
  autocapture: true,
});
```

Pass a user ID as the second argument when you already know it:

```ts
amplitude.init("YOUR_API_KEY", "user-12345", {
  autocapture: true,
});
```

If your project uses the EU data center, set `serverZone`:

```ts
amplitude.init("YOUR_API_KEY", {
  serverZone: "EU",
  autocapture: true,
});
```

`autocapture: true` turns on every autocapture feature that the SDK enables with a boolean, including element clicks, frustration interactions, failed network requests, and web vitals. To start with only the default set (page views, sessions, attribution, forms, and file downloads), omit `autocapture` or pass an object. For choices, go to [Autocapture](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2/usage-guide#autocapture).

### Fix initialization problems

| Symptom | Cause | Fix |
| --- | --- | --- |
| Console warning: ``options.defaultTracking` is set to undefined` | You didn't set `autocapture` (or the deprecated `defaultTracking`). | Not an error. Set `autocapture` explicitly to silence it. |
| Errors during server-side rendering, or no events from server-rendered pages | `init()` runs on the server (Next.js, Nuxt, SvelteKit, Remix). | Call `init()` only in browser code, for example in a client component or a `useEffect`. Go to the [Next.js installation guide](https://amplitude.com/docs/sdks/frameworks/nextjs-installation-guide). |
| Clicks or inputs stop working after `init()` in an Angular app | Zone.js wraps DOM APIs that autocapture also patches. | Call `init()` in `main.ts` before `bootstrapApplication`, or inside `NgZone.runOutsideAngular()`. |
| No page views, sessions, or attribution in a Chrome extension | In a Chrome extension, the SDK turns off default autocapture unless you enable each feature. This [default changed in 2.42.1](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2-release-notes#2421). | Set each feature explicitly, for example `autocapture: { pageViews: true, sessions: true }`. |
| Identity resets on every page load | The browser blocks cookies (private mode, strict tracking protection, or a sandboxed iframe), or the page runs on `file://`. | Serve the page over HTTP(S). If cookies stay blocked, set `identityStorage: "localStorage"`. |
| Events go to the wrong region, or ingestion returns `Invalid API key` | `serverZone` doesn't match the project's data center. | Set `serverZone: "EU"` for EU projects. Omit it for US projects. |

## Send a first event

Track one custom event and wait for the upload result. `track()` returns an object whose `promise` resolves after the SDK finishes the upload attempt.

```ts
const result = await amplitude.track("Sign Up Clicked", {
  plan: "starter",
}).promise;

console.log(result.code, result.message);
// 200 "Event tracked successfully"
```

The SDK uploads queued events about one second after the first one enters the queue, in requests of up to 30 events. The `promise` resolves after that upload, so expect about one second of delay.

### Fix upload problems

| `result.code` and `result.message` | Cause | Fix |
| --- | --- | --- |
| `0`, `Event skipped due to optOut config` | Opt-out is on for this browser. The SDK stores opt-out in its cookie, so it persists across loads. | Call `amplitude.setOptOut(false)`, or clear the `AMP_` cookies for your domain. |
| `0`, `Event skipped due to empty event type` | The event name is empty or not a string. | Pass a non-empty string as the first argument. |
| `400`, `Event rejected due to missing API key` | `init()` received an empty API key. | Check the variable that holds your key. Build tools often inline an empty value when an environment variable is missing. |
| `400`, `Invalid API key: ...` | The key is wrong, or belongs to a project in the other data center. | Copy the key again and check `serverZone`. |
| `500`, `Event rejected due to exceeded retry count`, after about 10 seconds | The request never reached Amplitude, and the SDK gave up after five attempts. Ad blockers, a Content Security Policy, CORS on a proxy, or a server error cause this. | Open the browser **Network** tab and check the request to `api2.amplitude.com` (or `api.eu.amplitude.com`). Add `https://*.amplitude.com` to `connect-src`. If an ad blocker blocks the request, route traffic through a [proxy](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2/usage-guide#send-events-through-a-proxy). |
| The promise never resolves | `init()` never ran on this instance, so the call is still queued. | Make sure `init()` runs before or after the call on the same instance, and that it isn't inside a branch that skips it. |
| The event disappears when the page navigates right after `track()` | The browser canceled the request when the page unloaded. | Keep the default `fetch` transport, which sends with `keepalive`. For large payloads, go to [Send events when the page unloads](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2/usage-guide#send-events-when-the-page-unloads). |

## Confirm the event in Amplitude

1. In Amplitude, open **User Lookup** and search for the user ID you passed, or for the device ID from `amplitude.getDeviceId()`.
2. Open the **Activity** tab and turn on **Live event updates**.
3. Confirm that `Sign Up Clicked` appears with the `plan` property.

If the event doesn't appear within a minute, follow [Verify events](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2/verify-events). It walks through each stage between `track()` and Amplitude's servers.

## Next steps

- Identify signed-in users with [`setUserId()`](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2/usage-guide#set-the-user-id), and call `reset()` when they sign out.
- Choose which [Autocapture](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2/usage-guide#autocapture) events to keep.
- Add the custom events and properties your tracking plan needs. Go to [Track events](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2/usage-guide#track-events).

