---
title: "Upload source maps with the CLI | Grafana Cloud documentation"
description: "Use the Faro CLI to upload source maps in CI/CD, with gzip and batch handling."
---

> For a curated documentation index, see [llms.txt](/llms.txt). For the complete documentation index, see [llms-full.txt](/llms-full.txt).

# Upload source maps with the CLI

Use the Faro CLI to upload source maps separately from your build process, particularly useful for CI/CD pipelines.

> Note
> 
> When using bundler plugins with the CLI, set `skipUpload: true` to skip uploading during builds and export the bundle ID to environment variables for CLI use.

## Install the CLI

Install the Faro CLI tool.

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
npm install --save-dev @grafana/faro-cli
```

or

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
yarn add --dev @grafana/faro-cli
```

> Warning
> 
> Always install `@grafana/faro-cli` as a project dependency before using it. Running `npx faro-cli` without installing the package first may download and execute a different `npm` package with the same name, which poses a security risk. Install the package explicitly with `npm install --save-dev @grafana/faro-cli` or `yarn add --dev @grafana/faro-cli` before running commands.

## Obtain an API key

To upload source maps with the CLI, you must generate a token for the API key value with the necessary permissions to upload source maps to Grafana Cloud. To generate a token, follow these steps:

1. Navigate to the [Grafana website](/).
2. Sign in to your account and then click **My Account** in the top right corner.
3. In the sidebar under **Security**, click **Access Policies** and then click **Create access policy**.
4. Select the `sourcemaps:read`, `sourcemaps:delete`, and `sourcemaps:write` scopes from the drop-down list.
5. After creating your access policy, click **Add token** in the card for your newly created policy.
6. **Create** the token and be sure to copy the token value, as you aren’t be able to see it again.

After you have generated a token with the API key value, you can use it in the Faro JavaScript bundler plugins to upload your source maps to Grafana Cloud. Use the generated token value as the `apiKey` value in the configuration options for the bundler plugins.

For best practices, store your token in a secure location and don’t expose it in your source code. Consider using environment variables or a secrets manager to securely store and access your API key.

## Upload source maps

Upload source maps using the CLI.

> Note
> 
> The Faro CLI uses `curl` for HTTP requests. If you’re running in an Alpine Docker container, install `curl` manually with `apk add curl` before running the CLI.

> Note
> 
> The source map upload endpoint differs from the Faro Collector endpoint. Use the endpoint shown in **Frontend Observability** &gt; **Settings** &gt; **Source Maps** &gt; **Configure source map uploads**.

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
npx faro-cli upload \
  --endpoint "$your-faro-sourcemap-api-url" \
  --app-id "$your-app-id" \
  --api-key "$your-api-key" \
  --stack-id "$your-stack-id" \
  --bundle-id env \
  --app-name "$your-app-name" \
  --output-path "./dist" \
  --verbose
```

## File size handling

The CLI handles large files automatically within the Faro API’s 30MB per file limit:

- Checks file sizes and warns about oversized files
- Streams files and creates upload batches as they approach size limits
- Supports tuning with `--max-upload-size` while respecting backend limits

## Compression options

Reduce bandwidth usage with these compression strategies:

Compress tarred contents for multiple files:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
npx faro-cli upload \
  --endpoint "$your-faro-sourcemap-api-url" \
  --app-id "$your-app-id" \
  --api-key "$your-api-key" \
  --stack-id "$your-stack-id" \
  --bundle-id "$your-bundle-id" \
  --output-path "./dist" \
  --patterns "*.map" \
  --gzip-contents \
  --verbose
```

Compress HTTP payload for large individual files:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
npx faro-cli upload \
  --endpoint "$your-faro-sourcemap-api-url" \
  --app-id "$your-app-id" \
  --api-key "$your-api-key" \
  --stack-id "$your-stack-id" \
  --bundle-id "$your-bundle-id" \
  --output-path "./dist" \
  --patterns "*.map" \
  --gzip-payload \
  --verbose
```

Combine both compression methods for maximum efficiency:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
npx faro-cli upload \
  --endpoint "$your-faro-sourcemap-api-url" \
  --app-id "$your-app-id" \
  --api-key "$your-api-key" \
  --stack-id "$your-stack-id" \
  --bundle-id "$your-bundle-id" \
  --output-path "./dist" \
  --patterns "*.map" \
  --gzip-contents \
  --gzip-payload \
  --verbose
```

## Use a proxy

Route source map uploads through a proxy server:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
npx faro-cli upload \
  --endpoint "$your-faro-sourcemap-api-url" \
  --app-id "$your-app-id" \
  --api-key "$your-api-key" \
  --stack-id "$your-stack-id" \
  --bundle-id "$your-bundle-id" \
  --output-path "./dist" \
  --proxy "$your-proxy:port" \
  --proxy-user "user:pass" \
  --verbose
```

## Inject bundle ID into JavaScript files

Add bundle IDs to built JavaScript files:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
npx faro-cli inject-bundle-id \
  --bundle-id "$your-bundle-id" \
  --app-name "$your-app-name" \
  --files "dist/**/*.js" \
  --verbose
```

Test the injection without making changes:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
npx faro-cli inject-bundle-id \
  --bundle-id "$your-bundle-id" \
  --app-name "$your-app-name" \
  --files "dist/**/*.js" \
  --dry-run \
  --verbose
```

## Generate cURL commands

Create ready-to-run cURL commands for source map uploads:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
npx faro-cli curl \
  --endpoint "$your-faro-sourcemap-api-url" \
  --app-id "$your-app-id" \
  --api-key "$your-api-key" \
  --stack-id "$your-stack-id" \
  --bundle-id "$your-bundle-id" \
  --file "./dist/main.js.map"
```

## Upload command options

**Required options:**

- `-e, --endpoint <url>` - Faro API endpoint URL from **Frontend Observability** &gt; **Settings** &gt; **Source Maps** &gt; **Configure source map uploads**
- `-a, --app-id <id>` - Faro application ID
- `-k, --api-key <key>` - Faro API key
- `-s, --stack-id <id>` - Faro stack ID from **Frontend Observability** &gt; **Settings** &gt; **Source Maps** &gt; **Configure source map uploads**
- `-b, --bundle-id <id>` - Bundle ID. Set to `env` to read from environment variable
- `-o, --output-path <path>` - Path to directory containing source maps

**Optional options:**

- `-n, --app-name <name>` - Application name for finding bundle ID in environment variables
- `-k, --keep-sourcemaps` - Keep source maps after uploading. Default: `false`
- `-g, --gzip-contents` - Compress source maps as tarball before uploading. Default: `false`
- `-z, --gzip-payload` - Gzip HTTP payload for smaller uploads. Default: `false`
- `-v, --verbose` - Enable detailed logging. Default: `false`
- `-r, --recursive` - Recursively search subdirectories for source maps. Default: `false`
- `-i, --max-upload-size <size>` - Maximum upload size in bytes. Default: 30MB
- `-x, --proxy <url>` - Proxy URL to route requests through. Supports HTTP and HTTPS proxies
- `-U, --proxy-user <user:password>` - Username and password for proxy authentication

## cURL command options

**Required options:**

- `-e, --endpoint <url>` - Faro API endpoint URL from **Frontend Observability** &gt; **Settings** &gt; **Source Maps** &gt; **Configure source map uploads**
- `-a, --app-id <id>` - Faro application ID
- `-k, --api-key <key>` - Faro API key
- `-s, --stack-id <id>` - Faro stack ID from **Frontend Observability** &gt; **Settings** &gt; **Source Maps** &gt; **Configure source map uploads**
- `-b, --bundle-id <id>` - Bundle ID. Set to `env` to read from environment variable
- `-f, --file <path>` - Path to source map file

**Optional options:**

- `-n, --app-name <name>` - Application name for finding bundle ID in environment variables
- `-t, --content-type <type>` - Content type for upload. Default: `application/json`
- `-z, --gzip-payload` - Generate command that compresses payload. Default: `false`
- `-x, --proxy <url>` - Proxy URL to route requests through. Supports HTTP and HTTPS proxies
- `-U, --proxy-user <user:password>` - Username and password for proxy authentication

After uploading, verify your source maps in Frontend Observability by navigating to **Settings** &gt; **Source Maps**. For troubleshooting common issues, refer to [Troubleshooting](/docs/grafana-cloud/monitor-applications/frontend-observability/sourcemap-uploads/troubleshooting/).
