# lpm download (/docs/packages/download)



```bash
lpm download <package[@version]> [--version <V>] [--output <DIR>]
```

Fetches a package tarball and extracts it into a directory you choose. **No lockfile**, &#x2A;*no `node_modules`**, **no script execution**, **no `package.json` mutation**. Just the bytes.

Useful for inspecting a package's contents before you trust it, archiving a snapshot for offline reference, generating a fixture, or reading the source of a package you don't want to install.

Routing matches [`lpm install`](/docs/packages/install):

* `@lpm.dev/*` fetches from LPM.dev Registry.
* `@scope/pkg` follows the current project's `.npmrc` `@scope:registry=...` mapping when one exists.
* Unscoped names (`react`, `zod`, `lodash.merge`) use the current project's default `.npmrc` registry, or npmjs.org when no override is present.

If you specifically mean an LPM.dev Registry package, prefer the fully scoped `@lpm.dev/owner.pkg` form.

When npm firewall mode is `monitor` or `enforce`, LPM CLI checks routed public npm packages with LPM Firewall at `firewall.lpm.dev` after selecting the version and before downloading the tarball. LPM Firewall is an LPM.dev Registry Pro/Org feature, so active modes send LPM.dev Registry auth; run `lpm login` locally, or use `LPM_TOKEN` / registry-audience OIDC in CI. `monitor` warns and continues when entitlement is denied, while `enforce` blocks packages whose effective firewall action is `block` or denied by entitlement before any package bytes are extracted. In human output, the download line shows `🔥 LPM Firewall active` when that check is active. LPM.dev Registry packages and other `.npmrc`-declared private/custom registry packages are not sent to the npm firewall verdict API. The legacy string `report` is still accepted as a `monitor` alias.

## Examples [#examples]

```bash
lpm download react                                   # npmjs.org (or project .npmrc default registry)
lpm download react@0.14.3                            # npm-style inline version
lpm download @my-co/internal                         # project .npmrc scoped registry
lpm download @lpm.dev/owner.pkg                      # force LPM.dev Registry
lpm download @lpm.dev/owner.pkg --version 2.1.0      # a specific version
lpm download react --version next                    # dist-tag or semver range
lpm download @lpm.dev/owner.pkg --json               # structured output (URL, integrity, paths)
```

## How it works [#how-it-works]

1. Fetches the package metadata from the routed registry to find the tarball URL and SRI integrity hash for the requested (or latest) version.
2. Downloads the tarball. Automatically followed redirects are checked before each hop; once the request chain has used HTTPS, a redirect to HTTP fails with `refused HTTPS-to-HTTP redirect`.
3. Verifies the SRI hash when the registry ships one. If the registry does not ship integrity, `lpm download` refuses to extract by default; re-run with `--allow-unverified` only when you intentionally accept an unverified tarball.
4. Extracts into the output directory.

The output directory defaults to the current working directory. The tarball's top-level `package/` is unwrapped during extraction (equivalent to `tar x --strip-components=1`), so you get the package contents directly.

Direct HTTP follows the same rules as [`lpm install`](/docs/packages/install): loopback is available for local development, and a deliberate registry `--insecure` override can allow a configured non-loopback HTTP endpoint. Neither case allows an HTTPS redirect to downgrade to HTTP. See [Redirect transport policy](/docs/registries#redirect-transport-policy).

## What `lpm download` does NOT do [#what-lpm-download-does-not-do]

* Install dependencies — none of the package's `dependencies` are fetched
* Touch `package.json` or any lockfile
* Run lifecycle scripts (`preinstall`, `postinstall`, etc.)
* Place the result in `node_modules/`
* Update the global content-addressable store

For a real install, use [`lpm install`](/docs/packages/install). For source delivery into your project, use [`lpm add`](/docs/packages/add).

## Flags [#flags]

| Flag                   | Effect                                                                                                                                                                       |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--version <V>`        | Version spec to download: exact version, dist-tag (`latest`, `next`), or semver range. Defaults to `latest`. Alternative to inline `package@version`; do not pass both.      |
| `--output <DIR>`, `-o` | Output directory (default: current working directory). The `output_dir` field in `--json` mode is canonicalized to an absolute path regardless of how the flag was passed.   |
| `--allow-unverified`   | Waive the default integrity gate when the registry returns no SRI hash. Intended for legacy sources that genuinely do not ship integrity; you take on verification yourself. |

Plus the [global flags](/docs/commands#global-flags).

## `--json` envelope [#--json-envelope]

```json
{
  "success": true,
  "package": "@lpm.dev/owner.pkg",
  "version": "2.1.0",
  "tarball_url": "https://lpm.dev/api/registry/@lpm.dev/owner.pkg/-/owner.pkg-2.1.0.tgz",
  "integrity": "sha512-...",
  "integrity_verified": true,
  "size_bytes": 87654,
  "output_dir": "/abs/path/to/output",
  "files_extracted": 42,
  "elapsed_secs": 0.412
}
```

Fields:

| Field                | Meaning                                                                                                                                                                                                           |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tarball_url`        | Resolved tarball URL the bytes came from. Useful for mirroring or audit logs.                                                                                                                                     |
| `integrity`          | SRI string the registry advertised for this version (e.g. `sha512-…`), or `null` if the registry didn't ship one. A `null` value only reaches a success envelope when you explicitly passed `--allow-unverified`. |
| `integrity_verified` | `true` when the SRI was present and verified, `false` only on the explicit `--allow-unverified` path where extraction proceeds without a registry-provided hash. A verification failure still aborts the run.     |
| `output_dir`         | Absolute path where files were extracted (canonicalized).                                                                                                                                                         |
| `files_extracted`    | Count of files written from the tarball, after the `package/` prefix is stripped.                                                                                                                                 |

## See also [#see-also]

* [`lpm install`](/docs/packages/install) — full install, with `node_modules` and lockfile
* [`lpm add`](/docs/packages/add) — source delivery into your project
* [`lpm info`](/docs/packages/info) — package metadata without downloading
* [`lpm resolve`](/docs/packages/resolve) — print the resolved dep tree without downloading
