# Compatibilidad con S3

Los Storage Buckets se pueden acceder a través de una **API compatible con S3**, lo que permite utilizar herramientas S3 existentes —la AWS CLI, `boto3`, `s5cmd` y la mayoría de los demás SDK de S3— contra tus buckets sin modificar el código. Las solicitudes pasan por un servicio de gateway en `https://s3.hf.co`.

La API de S3 es una de varias formas de acceder a los datos de un bucket. Para el acceso nativo de Hugging Face (la CLI `hf`, las rutas `hf://` y las monturas de sistema de archivos) sin credenciales de S3 separadas, consulte [Patrones de acceso](./storage-buckets-access).

> [!NOTE]
> La API de S3 solo funciona con [Storage Buckets](./storage-buckets). No expone otros tipos de repositorios de Hugging Face (modelos, datasets, Spaces).

## Generar credenciales de S3

La pasarela se autentica con claves de acceso de estilo AWS derivadas de un [User Access Token](./security-tokens) de Hugging Face.

1. Vaya a su configuración de [Access Tokens](https://huggingface.co/settings/tokens). Cree un token con el botón **Create new token** si aún no tiene uno. Los permisos del token se convierten en los permisos de las credenciales de S3: elija **Read** para acceso de solo lectura a sus buckets, o **Write** para acceso de lectura y escritura.
2. Busca el token en la lista, abre su menú desplegable y elige **Generate S3 credentials**.

   
   
   
   

3. Copia el **access key ID** generado (con el prefijo `HFAK…`) y la **secret access key** en un lugar seguro: la clave secreta solo se muestra una vez.

Las credenciales de S3 heredan los permisos del token de acceso subyacente. Para los tokens de granularidad fina, delimítelos a los espacios de nombres y cubos que pretenda utilizar.

> [!TIP]
> Para los flujos de trabajo automatizados que acceden a los buckets de una organización, también puede generar credenciales de S3 a partir de un token de [cuenta de servicio](./enterprise-service-accounts#generating-s3-credentials) en lugar de un token de acceso de usuario.

## Configuración de un cliente

Apunte su cliente S3 al endpoint de la pasarela y configure algunas opciones requeridas. Use su **namespace** de Hugging Face (su nombre de usuario o el nombre de una organización) en la URL del endpoint; consulte [Addressing buckets](#addressing-buckets) a continuación.

| Configuración                        | Valor                          | Por qué                                                           |
|--------------------------------|--------------------------------|---------------------------------------------------------------|
| `endpoint_url`                 | `https://s3.hf.co/<namespace>` | La pasarela, limitada a tu espacio de nombres                         |
| `region`                       | `us-east-1`                    | Obligatorio; la puerta de enlace es actualmente de una sola región              |
| `s3.addressing_style`          | `path`                         | Los buckets se dirigen como segmentos de ruta, no como subdominios        |
| `request_checksum_calculation` | `when_required`                | Impide que los clientes recientes envíen sumas de verificación finales       |
| `response_checksum_validation` | `when_required`                | Impide que los clientes recientes esperen sumas de verificación en las respuestas |

Los dos ajustes de sumas de verificación son importantes para los clientes recientes: AWS CLI ≥ 2.23 y las versiones recientes de `boto3` envían sumas de verificación CRC32 finales (mediante el encuadre `aws-chunked`) de forma predeterminada, lo cual la pasarela no analiza. Estos ajustes indican al cliente que envíe sumas de verificación solo cuando una operación las requiera estrictamente.

Los siguientes son opcionales pero recomendados. Con el valor predeterminado del cliente de 8 MB, un archivo grande se divide en muchas partes; 256 MB significa muchas menos partes por carga, mientras que cada parte se mantiene lo suficientemente pequeña para que la pasarela la procese de manera eficiente:

| Configuración                  | Valor   |
|--------------------------|---------|
| `s3.multipart_threshold` | `256MB` |
| `s3.multipart_chunksize` | `256MB` |

### Ejemplo: perfil de AWS CLI

Agrega un perfil a `~/.aws/config`:

```ini
[profile hf]
region = us-east-1
endpoint_url = https://s3.hf.co/<namespace>
s3 =
    addressing_style = path
    multipart_threshold = 256MB
    multipart_chunksize = 256MB
request_checksum_calculation = when_required
response_checksum_validation = when_required
```
Nota: reemplace el `<namespace>` anterior con el nombre de usuario u organización en el que se almacenan sus buckets.

Agrega las credenciales correspondientes al perfil en `~/.aws/credentials`:

```ini
[hf]
aws_access_key_id = HFAK...
aws_secret_access_key = ...
```

Luego, use cualquier comando de S3 con el perfil:

```bash
aws --profile hf s3 ls
aws --profile hf s3 mb s3://my-bucket
aws --profile hf s3 cp ./model.safetensors s3://my-bucket/models/model.safetensors
```

## Dirección de cubos

AWS S3 utiliza un espacio plano y globalmente único de nombres de cubos, y los SDK esperan que el nombre de un cubo sea una cadena simple sin `/`. Los cubos de Hugging Face se identifican en cambio como `namespace/bucket`, donde el `namespace` es tu nombre de usuario u organización. Ese nivel adicional introduce una incompatibilidad con los clientes de S3: muchos no aceptan una `/` en el nombre de un cubo, o la escapan incorrectamente en la URL. Hay dos formas de evitarlo:

**1. Incluir el espacio de nombres en la URL del punto de acceso** (recomendado para la mayoría de los casos). Esto limita todas las operaciones a ese espacio de nombres, por lo que el nombre del bucket que se pasa al cliente es simplemente el nombre del bucket de HF. Funciona bien para tus propios buckets o para buckets de una sola organización, pero falla entre espacios de nombres, por ejemplo, una copia en el servidor desde un bucket personal a un bucket de organización.

```bash
aws --endpoint-url https://s3.hf.co/my-org s3api get-object \
  --bucket my-bucket --key some/object.txt ./object.txt
```

**2. Trate el espacio de nombres como el cubo** y anteponga el nombre del cubo de HF a la clave del objeto. Esto funciona para operaciones a nivel de objeto (subidas, descargas), pero presenta problemas con operaciones a nivel de cubo, como la creación o eliminación de cubos.

```bash
aws --endpoint-url https://s3.hf.co s3api get-object \
  --bucket my-org --key my-bucket/some/object.txt ./object.txt
```

## Limitaciones y diferencias con AWS S3

Dado que los Storage Buckets no modelan todos los conceptos de S3, algunos comportamientos difieren o no están admitidos.

### Descargas de objetos

La pasarela es actualmente de una sola región. Para mejorar el rendimiento de las descargas, `GetObject` suele responder con una redirección HTTP 302 al borde más cercano de la CDN de Hugging Face, en lugar de servir los bytes directamente.

Algunos SDK no siguen las redirecciones desde un endpoint de S3, por lo que la puerta de detección identifica a los clientes que se identifican como `aws-cli`, `botocore` (que cubre a `boto3`) o `aws-sdk-rust` y les proxy los datos a través de sí misma. Todos los demás clientes (`rclone`, `s5cmd`, `curl`, el SDK de AWS para Go, etc.) reciben el 302 y lo siguen de forma nativa, manteniendo la puerta de detección fuera de la ruta de datos para descargas más rápidas.

### Nomenclatura de claves de objetos

Las claves de los objetos de bucket están más restringidas que en S3. Una clave no debe **contener**:

- comienza o termina con `/`
- contener barras diagonales consecutivas (`//`)
- contener secuencias `../`
- comienza con `./`
- terminar con `..`
- contienen barras invertidas (`\`) o bytes nulos (`\0`)

### ListObjects

- `ListObjectsV1` no se admite; use `ListObjectsV2`. Tenga en cuenta que algunos clientes (como rclone) pueden necesitar configurarse para usar exclusivamente `ListObjectsV2`.
- Solo se permite `/` como delimitador.

### Otras diferencias de API

- **Metadatos del objeto**: los metadatos de usuario arbitrarios (`x-amz-meta-*`) no se almacenan ni se devuelven. Se admite `Content-Type`.
- **Funciones no compatibles**: las ACL, las políticas de cubo, la etiquetado de objetos, la versionado de objetos, las reglas de ciclo de vida, la cifrado del lado del servidor (SSE) y las notificaciones de cubo no son compatibles. Los objetos siempre se informan con la clase de almacenamiento `STANDARD`. Las cabeceras y parámetros de solicitud relacionados se aceptan pero se ignoran.
- **CopyObject**: la copia en el lado del servidor solo funciona dentro de un único espacio de nombres. No se admiten copias entre espacios de nombres ni `UploadPartCopy` (copiar una parte de un objeto existente en una carga multipartita).
- **Solicitudes condicionales**: las precondiciones `If-Match` / `If-None-Match` se respetan en `PutObject` y en la fuente de copia de `CopyObject`, pero no en `GetObject`.
- **Vencimiento de la carga multipart**: las cargas multipart en curso que nunca se completan ni se interrumpen vencen y se limpian automáticamente después de 7 días.

## Ejemplos

Recetas para el mundo real de tareas comunes. Cada una se basa en la [configuración del cliente](#configuring-a-client) anterior.

### Leer y escribir con `boto3`

[`boto3`](https://docs.aws.amazon.com/boto3/latest/) funciona con la puerta de enlace mediante la [configuración del cliente](#configuring-a-client) anterior. Sustituye `<namespace>` por tu nombre de usuario u organización:

```python
import boto3
from botocore.config import Config

s3 = boto3.client(
    "s3",
    endpoint_url="https://s3.hf.co/<namespace>",
    aws_access_key_id="HFAK...",
    aws_secret_access_key="...",
    config=Config(
        region_name="us-east-1",
        s3={"addressing_style": "path"},
        request_checksum_calculation="when_required",
        response_checksum_validation="when_required",
    ),
)

s3.upload_file("model.safetensors", "my-bucket", "models/model.safetensors")
s3.download_file("my-bucket", "models/model.safetensors", "model.safetensors")
```

### Consultar un bucket con DuckDB

En DuckDB 2.0 o posterior, la extensión `httpfs` lee directamente las rutas `hf://buckets/`, y con la extensión `hf` también puede escribir en Buckets. Consulte [Consultar con DuckDB](./storage-buckets-access#query-with-duckdb).

Para versiones anteriores de DuckDB, o para escribir los resultados de una consulta de vuelta en un bucket con `COPY ... TO` sin la extensión, utilice la pasarela S3:

```sql
INSTALL httpfs;
LOAD httpfs;

CREATE SECRET hf (
    TYPE s3,
    KEY_ID 'HFAK...',
    SECRET '...',
    ENDPOINT 's3.hf.co/<namespace>',
    URL_STYLE 'path',
    REGION 'us-east-1'
);

SELECT * FROM read_parquet('s3://my-bucket/data.parquet');
```

> [!NOTE]
> Se requiere `URL_STYLE 'path'`. Sin él, DuckDB usa una dirección de estilo virtual-hosted (`my-bucket.s3.hf.co`), que la puerta de enlace no sirve; verás un error de "Could not resolve hostname".

### Importar datos usando `rclone`

[`rclone`](https://rclone.org/) es una forma práctica de copiar datos entre dos almacenes compatibles con S3, por lo que es una buena opción para mover un bucket de AWS S3 existente (o cualquier origen compatible con S3) a un Storage Bucket.

> [!TIP]
> ¿Estás moviendo un conjunto de datos grande? Al montar la fuente y ejecutar `hf sync`, la deduplicación se realiza en el cliente, por lo que normalmente se suben menos bytes que con rclone. Consulta la [Guía de migración](./storage-buckets-migration).

La idea es declarar dos remotos: tu bucket de origen y la pasarela de Hugging Face, y dejar que `rclone` transmita los objetos entre ellos. Añade ambos remotos a `~/.config/rclone/rclone.conf`. El primero apunta a tu bucket S3 existente; ajústalo para que coincida con tu origen (aquí, AWS S3 plano):

```ini
[aws]
type = s3
provider = AWS
access_key_id = AKIA...
secret_access_key = ...
region = us-east-1
```

El segundo apunta a la pasarela de Hugging Face. Como con cualquier otro cliente, delimite el punto de finalización a su [namespace](#addressing-buckets), use la dirección `path`, fuerce ListObjectsV2 (la única versión de listado que admite la pasarela) y establezca un tamaño de parte de 256M. Eso es mucho mayor que el valor predeterminado de 5M de rclone, por lo que los archivos grandes se suben en menos partes, y es lo suficientemente pequeño para que la pasarela lo procese de forma eficiente y para mantener la memoria de rclone bajo control (mantiene 4 partes por transferencia en memoria):

```ini
[hf]
type = s3
provider = Other
endpoint = https://s3.hf.co/<namespace>
access_key_id = HFAK...
secret_access_key = ...
region = us-east-1
force_path_style = true
list_version = 2
upload_cutoff = 256M
chunk_size = 256M
```

Nota: reemplace el `<namespace>` anterior con el nombre de usuario u organización en el que se almacenan sus buckets, y use las [credenciales de S3](#generating-s3-credentials) generadas a partir de su token de acceso. El bucket de destino debe existir previamente bajo ese namespace.

Ahora copie un bucket de origen en su bucket de almacenamiento:

```bash
rclone copy aws:my-source-bucket hf:my-bucket --progress
```

`rclone copy` solo transfiere los objetos que faltan o han cambiado en el destino, por lo que es seguro volver a ejecutarlo para reanudar una importación interrumpida o incorporar objetos nuevos. Para que el destino sea un espejo exacto de la fuente, eliminando los objetos del destino que ya no existen en la fuente, use `rclone sync` en su lugar:

```bash
rclone sync aws:my-source-bucket hf:my-bucket --progress
```

> [!TIP]
> Para importaciones grandes, añade `--transfers` y `--checkers` para aumentar la concurrencia (p. ej. `--transfers 16 --checkers 16`) y, a continuación, ejecuta `rclone check aws:my-source-bucket hf:my-bucket` para confirmar que todos los objetos se hayan transferido correctamente.

### Versionar datos con DVC

[DVC](https://dvc.org/) versiona conjuntos de datos y modelos en git manteniendo archivos de puntero pequeños en el repositorio y subiendo los datos reales a un remoto. Un bucket funciona como un remoto de DVC a través de la pasarela, por lo que tu código y los punteros `.dvc` permanecen en git mientras los datos se almacenan en tu bucket. Instala DVC con soporte para S3 (`pip install 'dvc[s3]'`) y luego añade el remoto usando la [configuración del cliente](#configuring-a-client) anterior:

```bash
dvc remote add -d hf-bucket s3://my-bucket/dvc-store
dvc remote modify hf-bucket endpointurl https://s3.hf.co/<namespace>
dvc remote modify hf-bucket region us-east-1
```

Pase las [credenciales de S3](#generating-s3-credentials) a través del entorno, o con `dvc remote modify --local` para que no queden en git:

```bash
export AWS_ACCESS_KEY_ID=HFAK...
export AWS_SECRET_ACCESS_KEY=...
```

Luego, realiza el seguimiento, sube y descarga como de costumbre: `dvc push` sube al bucket y `dvc pull` en un clon nuevo lo descarga de nuevo:

```bash
dvc add data/
git add data.dvc .gitignore .dvc/config && git commit -m "Track data with DVC"
dvc push
```

> [!NOTE]
> Usa tu [namespace](#addressing-buckets) en `endpointurl` y el nombre del bucket sin prefijos en la URL `s3://`.

