> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/astral-sh/uv/llms.txt
> Use this file to discover all available pages before exploring further.

# Package Indexes

> Configure custom PyPI indexes, private registries, and index priorities in uv

By default, uv uses the [Python Package Index (PyPI)](https://pypi.org) for dependency resolution and package installation. However, uv can be configured to use other package indexes, including private indexes.

## Defining an Index

To include an additional index when resolving dependencies, add a `[[tool.uv.index]]` entry to your `pyproject.toml`:

```toml pyproject.toml theme={null}
[[tool.uv.index]]
# Optional name for the index
name = "pytorch"
# Required URL for the index
url = "https://download.pytorch.org/whl/cpu"
```

<ParamField path="name" type="string">
  Optional identifier for the index. Must contain only alphanumeric characters, dashes, underscores, and periods (valid ASCII).
</ParamField>

<ParamField path="url" type="string" required>
  The URL of the package index (Simple API endpoint).
</ParamField>

### Command-Line Usage

Indexes can also be provided via command line or environment variables:

```bash theme={null}
# Command line with name
uv lock --index pytorch=https://download.pytorch.org/whl/cpu

# Environment variable
export UV_INDEX="pytorch=https://download.pytorch.org/whl/cpu"
uv lock
```

## Index Priority

Indexes are prioritized in the order they're defined:

1. Command-line indexes (highest priority)
2. Configuration file indexes (in order of appearance)
3. Default index (lowest priority)

The first index listed is the first consulted when resolving dependencies.

### Default Index

By default, uv includes PyPI as the "default" index (used when a package is not found on other indexes). To replace PyPI with a different default index:

```toml pyproject.toml theme={null}
[[tool.uv.index]]
name = "private-pypi"
url = "https://private.example.com/simple"
default = true
```

<ParamField path="default" type="boolean" default={false}>
  Mark this index as the default. The default index is always treated as lowest priority, regardless of position.
</ParamField>

Command-line equivalent:

```bash theme={null}
uv lock --default-index https://private.example.com/simple

# Or via environment variable
export UV_DEFAULT_INDEX="https://private.example.com/simple"
```

## Pinning Packages to an Index

Pin a package to a specific index using `tool.uv.sources`:

```toml pyproject.toml theme={null}
[tool.uv.sources]
torch = { index = "pytorch" }

[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"
```

This ensures `torch` is always installed from the `pytorch` index.

### Platform-Specific Indexes

Use environment markers to select indexes by platform:

```toml pyproject.toml theme={null}
[project]
dependencies = ["torch"]

[tool.uv.sources]
torch = [
  { index = "pytorch-cu118", marker = "sys_platform == 'darwin'"},
  { index = "pytorch-cu124", marker = "sys_platform != 'darwin'"},
]

[[tool.uv.index]]
name = "pytorch-cu118"
url = "https://download.pytorch.org/whl/cu118"

[[tool.uv.index]]
name = "pytorch-cu124"
url = "https://download.pytorch.org/whl/cu124"
```

## Explicit Indexes

Mark an index as `explicit = true` to prevent packages from being installed from it unless explicitly pinned:

```toml pyproject.toml theme={null}
[tool.uv.sources]
torch = { index = "pytorch" }

[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"
explicit = true
```

<ParamField path="explicit" type="boolean" default={false}>
  When true, packages can only be installed from this index if explicitly pinned via `tool.uv.sources`.
</ParamField>

<Note>
  Named indexes referenced via `tool.uv.sources` must be defined within the project's `pyproject.toml`. Indexes provided via command-line, environment variables, or user-level configuration will not be recognized.
</Note>

## Index Search Strategies

Control how uv searches across multiple indexes using the `--index-strategy` option or `UV_INDEX_STRATEGY` environment variable:

### first-index (Default)

Search for each package across all indexes, limiting candidate versions to those present in the first index that contains the package.

```bash theme={null}
uv sync --index-strategy first-index
```

This prevents "dependency confusion" attacks where an attacker publishes a malicious package on PyPI with the same name as an internal package.

### unsafe-first-match

Search across all indexes, but prefer the first index with a compatible version, even if newer versions are available on other indexes.

```bash theme={null}
uv sync --index-strategy unsafe-first-match
```

### unsafe-best-match

Search across all indexes and select the best version from the combined set of candidate versions (closest to pip's behavior).

```bash theme={null}
uv sync --index-strategy unsafe-best-match
```

<Warning>
  The `unsafe-best-match` strategy exposes users to "dependency confusion" attacks. See the [torchtriton attack](https://pytorch.org/blog/compromised-nightly-dependency/) for an example.
</Warning>

## Authentication

Most private package indexes require authentication. See the [Authentication documentation](/configuration/authentication) for detailed information.

### Credentials via Environment Variables

Provide credentials without storing them in plaintext:

```toml pyproject.toml theme={null}
[[tool.uv.index]]
name = "internal-proxy"
url = "https://example.com/simple"
```

```bash theme={null}
export UV_INDEX_INTERNAL_PROXY_USERNAME=public
export UV_INDEX_INTERNAL_PROXY_PASSWORD=koala
```

The environment variable name follows the pattern `UV_INDEX_<NORMALIZED_NAME>_USERNAME` and `UV_INDEX_<NORMALIZED_NAME>_PASSWORD`, where `<NORMALIZED_NAME>` is the uppercase index name with non-alphanumeric characters replaced by underscores.

### Credentials in URL

Alternatively, embed credentials directly in the URL:

```toml pyproject.toml theme={null}
[[tool.uv.index]]
name = "internal"
url = "https://public:koala@pypi-proxy.corp.dev/simple"
```

<Warning>
  Credentials are never stored in the `uv.lock` file. uv must have access to authenticated URLs at installation time.
</Warning>

### Authentication Behavior

Control when uv searches for credentials:

<ParamField path="authenticate" type="string" default="auto">
  Controls credential discovery behavior:

  * `"auto"`: Attempt unauthenticated request first, search for credentials on failure
  * `"always"`: Always search for credentials before making requests (required for some indexes like GitLab)
  * `"never"`: Never search for credentials (prevents credential leaking)
</ParamField>

```toml pyproject.toml theme={null}
[[tool.uv.index]]
name = "gitlab"
url = "https://gitlab.example.com/api/v4/projects/123/packages/pypi/simple"
authenticate = "always"
```

<Note>
  If a username is set, uv will search for credentials before making an unauthenticated request, regardless of the `authenticate` setting.
</Note>

## Error Handling

### Ignored Error Codes

When using the `first-index` strategy, uv stops searching across indexes on HTTP 401 or 403 errors. Customize this behavior:

```toml pyproject.toml theme={null}
[[tool.uv.index]]
name = "private-index"
url = "https://private-index.com/simple"
authenticate = "always"
ignore-error-codes = [403]
```

<ParamField path="ignore-error-codes" type="array">
  List of HTTP status codes to ignore when searching across indexes. uv will continue to the next index if these codes are encountered.
</ParamField>

<Info>
  uv always continues searching on 404 Not Found errors. This cannot be overridden.
</Info>

## Cache Control

Customize caching behavior for an index:

```toml pyproject.toml theme={null}
[[tool.uv.index]]
name = "example"
url = "https://example.com/simple"
cache-control = { api = "max-age=600", files = "max-age=365000000, immutable" }
```

<ParamField path="cache-control" type="object">
  Override HTTP cache control headers:

  * `api`: Controls caching for Simple API requests (package metadata)
  * `files`: Controls caching for artifact downloads (wheels and source distributions)
</ParamField>

By default, uv respects the cache control headers provided by the index. PyPI uses:

* Metadata: `max-age=600` (10 minutes)
* Artifacts: `max-age=365000000, immutable` (indefinite)

Force revalidation:

```toml pyproject.toml theme={null}
[[tool.uv.index]]
name = "example"
url = "https://example.com/simple"
cache-control = { api = "no-cache" }
```

## Flat Indexes

In addition to PyPI-style registries (PEP 503), uv supports "flat" indexes (local directories or HTML pages with flat lists of wheels and source distributions):

```toml pyproject.toml theme={null}
[[tool.uv.index]]
name = "local-packages"
url = "/path/to/directory"
format = "flat"
```

<ParamField path="format" type="string" default="simple">
  Index format:

  * `"simple"`: PyPI-style registry (PEP 503 Simple Repository API)
  * `"flat"`: Flat index (equivalent to pip's `--find-links`)
</ParamField>

Flat indexes support the same features as Simple API indexes, including `explicit = true` and pinning via `tool.uv.sources`.

## Legacy pip Compatibility

For compatibility with pip, uv supports `--index-url` and `--extra-index-url`:

```bash theme={null}
# pip-style (legacy)
uv pip install --index-url https://test.pypi.org/simple package-name

# uv-style (recommended)
uv pip install --default-index https://test.pypi.org/simple package-name
```

Mapping:

* `--index-url` → `--default-index` (sets default index)
* `--extra-index-url` → `--index` (adds additional index)

These can be combined with `[[tool.uv.index]]` configuration and follow the same prioritization rules.

## Examples

### Multiple Indexes with Priority

```toml pyproject.toml theme={null}
# PyTorch is checked first
[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"

# Internal index is checked second
[[tool.uv.index]]
name = "internal"
url = "https://internal.example.com/simple"

# Custom default replaces PyPI (checked last)
[[tool.uv.index]]
name = "private-pypi"
url = "https://private.pypi.example.com/simple"
default = true
```

### Private Registry with Authentication

```toml pyproject.toml theme={null}
[[tool.uv.index]]
name = "private"
url = "https://pypi.private.example.com/simple"
authenticate = "always"
ignore-error-codes = [403]
cache-control = { api = "max-age=600" }
```

```bash theme={null}
export UV_INDEX_PRIVATE_USERNAME=myuser
export UV_INDEX_PRIVATE_PASSWORD=mytoken
uv sync
```

### Explicit Index for Specific Packages

```toml pyproject.toml theme={null}
[project]
dependencies = ["torch", "numpy"]

[tool.uv.sources]
# Only torch comes from pytorch index
torch = { index = "pytorch" }

# PyTorch index is only used for explicitly pinned packages
[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"
explicit = true

# All other packages come from PyPI (default)
```

## Related Resources

* [Authentication](/configuration/authentication) - Index authentication methods
* [Alternative Indexes Guide](/guides/integration/alternative-indexes) - Provider-specific setup (AWS, Azure, GCP)
* [Configuration Files](/configuration/files) - Configure indexes in pyproject.toml
