Qué es una URL prefirmada (presigned URL)

Una URL prefirmada es un enlace temporal que da acceso a un archivo privado sin pedir login ni credenciales a quien lo abre. La firma prueba que el dueño autorizó ese acceso, y la URL deja de funcionar al expirar.

Actualizado el 6 min de lectura

Objetivos de aprendizaje

Después de leer este artículo podrás:

  • Entender cómo una URL prefirmada da acceso sin login
  • Generar una URL prefirmada de descarga y de subida en Python
  • Saber cuándo usar una URL prefirmada y cuándo un enlace revocable
En esta página

Imagina que guardas facturas, contratos o fotos de usuarios en un storage privado. Nadie de afuera debe abrirlos, pero de vez en cuando un usuario necesita descargar el suyo. No quieres crearle una cuenta en el storage ni hacer pasar el archivo por tu servidor.

La URL prefirmada resuelve eso: entrega un enlace que funciona por poco tiempo y solo para ese archivo. En inglés se llama presigned URL (también signed URL o pre-signed URL). Amazon S3 y Google Cloud Storage la ofrecen, y Azure Blob Storage tiene un equivalente llamado shared access signature (SAS).

Clientenavegadoro appTu backendfirma la URL consu clave secreta2Storagearchivo privado1pide acceso3URL prefirmada4GET/PUT directoexpira pronto
El backend firma la URL sin llamar al storage; el archivo viaja directo entre el cliente y el storage.

¿Cómo funciona una URL prefirmada?#

Una URL prefirmada es una URL normal con parámetros extra en la query string. Indican el archivo, el método HTTP (GET para descargar, PUT para subir) y hasta cuándo vale el enlace. El último parámetro es la firma: un hash calculado con una clave secreta que solo conoce el dueño del storage.

Cuando alguien abre el enlace, el storage repite el cálculo con los mismos datos. Si la firma coincide y el plazo no venció, entrega el archivo. Si alguien cambia el nombre del archivo o alarga el plazo en la URL, la firma deja de coincidir y la petición se rechaza.

Dos detalles importan en la práctica:

  • La URL lleva la autoridad de quien la generó. En Amazon S3 la URL usa las credenciales del usuario que la firmó. Quien recibe el enlace no necesita credenciales ni permisos.
  • Firmar no llama al storage. Tu backend firma de forma local, sin red. Solo quien abre el enlace habla con el storage.

¿Para qué sirve una URL prefirmada?#

  • Descargar un archivo privado: el usuario autenticado hace clic en "descargar factura" y recibe un enlace que vale unos minutos.
  • Subir directo desde el navegador: la app genera una URL de PUT y el navegador envía el archivo al storage. El archivo no pasa por tu servidor, lo que ahorra ancho de banda y memoria.
  • Enviar un archivo a terceros: un socio necesita recibir un informe una vez, sin cuenta ni contraseña.
  • Contenido protegido: imágenes o videos que solo ven los usuarios de pago.

¿Cómo generar una URL prefirmada en Python?#

El ejemplo usa boto3, el SDK de AWS para Python, que también funciona con storages compatibles con S3. Instálalo con pip install boto3 requests. Las credenciales vienen de variables de entorno, nunca del código.

python
import os

import boto3
import requests
from botocore.config import Config

s3 = boto3.client(
    "s3",
    region_name=os.environ.get("S3_REGION", "us-east-1"),
    endpoint_url=os.environ.get("S3_ENDPOINT"),  # omítelo en AWS S3; defínelo en otro storage compatible con S3
    aws_access_key_id=os.environ["S3_ACCESS_KEY"],
    aws_secret_access_key=os.environ["S3_SECRET_KEY"],
    config=Config(signature_version="s3v4"),
)

download_url = s3.generate_presigned_url(  # descarga, vale 10 minutos
    ClientMethod="get_object",
    Params={"Bucket": "mi-bucket", "Key": "facturas/2026-10.pdf"},
    ExpiresIn=600,
)

upload_url = s3.generate_presigned_url(  # subida, vale 5 minutos
    ClientMethod="put_object",
    Params={"Bucket": "mi-bucket", "Key": "uploads/foto.jpg"},
    ExpiresIn=300,
)

print(requests.get(download_url).status_code)  # 200
with open("foto.jpg", "rb") as f:
    print(requests.put(upload_url, data=f).status_code)  # 200

Si omites ExpiresIn, boto3 usa 3600 segundos (1 hora). El método HTTP de la petición debe ser el mismo para el que se generó la URL: una URL de GET no sirve para PUT.

Para probar sin Python, copia la download_url y ejecuta curl -o factura.pdf "<url>". Las comillas son obligatorias porque la URL tiene varios &.

¿Cuánto dura una URL prefirmada y se puede revocar?#

El plazo lo defines tú, dentro del límite del storage. En Amazon S3, la documentación oficial da estas cifras: hasta 12 horas si el enlace se crea en la consola, y hasta 7 días con el SDK o la CLI usando credenciales de usuario IAM. Con credenciales temporales, como las de un rol, la URL expira junto con ellas aunque hayas pedido más tiempo. Los 7 días valen para la firma SigV4; otros storages tienen topes propios (Google Cloud Storage también admite como máximo 7 días).

Revocar es el punto débil. La URL no queda registrada en ningún lugar: vale por su firma, y no hay un botón para cancelar un enlace concreto. Las opciones reales son desactivar o borrar la credencial usada para firmar (lo que invalida todas las URL firmadas con ella), borrar o mover el archivo, o usar un mecanismo de enlace revocable en lugar de una URL prefirmada.

Por eso la regla práctica es generar URL de vida corta en el momento en que el usuario las pide y nunca guardar la URL ya hecha en la base de datos.

¿Qué precauciones de seguridad tomar?#

  • Trata la URL como una contraseña. Quien la tenga accede al archivo. Mantenla fuera de logs, analytics y mensajes públicos.
  • Usa plazos cortos. Minutos para una descarga en pantalla, algo más para subir archivos grandes.
  • Limita los permisos de quien firma. Una URL solo puede lo que puede la credencial que la firmó. Usa una credencial restringida al bucket necesario.
  • Valida la subida después. Una URL de PUT acepta lo que se envíe. Revisa tamaño y tipo del archivo en tu backend tras el envío, o usa un POST prefirmado (generate_presigned_post), que acepta condiciones de tamaño y de tipo de contenido.
  • Mantén el reloj sincronizado. Un reloj desfasado puede invalidar la firma y causar errores como SignatureDoesNotMatch en S3. Sincroniza el servidor con NTP.

¿URL prefirmada o enlace para compartir: cuál usar?#

URL prefirmada Enlace para compartir
Validez Corta, definida al crearla Más larga
Revocable No Sí
Quién la crea Tu código, al momento Tú, una vez, por archivo
Ideal para Descarga o subida puntual, por usuario Archivo que compartes y quizá quieras cancelar

Si el enlace se usa en segundos o minutos, la URL prefirmada es la opción correcta. Si compartes el enlace con varias personas durante días y quizá necesites cancelarlo, usa un mecanismo revocable. Para decidir qué dejar público y qué privado, mira archivos públicos o privados. Para ver dónde encaja boto3, lee qué es S3 y el almacenamiento compatible con S3 y, para archivos grandes, carga multiparte y reanudable.

Cómo hacerlo en Square Cloud#

En el Blob Storage de Square Cloud, el caso del inicio (facturas y contratos que solo su dueño descarga) va en el bucket private, y el código Python de este artículo funciona con tres cambios: el endpoint https://s3-blob.squarecloud.app, la región auto y las claves S3 que generas a partir de una API key en la pestaña "Acceso S3" del panel. Las URL prefirmadas SigV4 valen hasta 7 días y sirven para descargar (GET) y para subir directo desde el navegador (PUT): el CORS acepta PUT desde cualquier origen, siempre que la API key tenga permiso de escritura.

Cuando el enlace sale del panel y no de tu código, la elección es la misma de la tabla anterior. El enlace temporal vale hasta 24 horas y no se puede revocar. El enlace para compartir vale hasta 30 días y se puede revocar en cualquier momento; la contraseña y los metadatos en el enlace están en los planes Pro y Enterprise.

El Blob no cobra tarifa de salida ni de entrada, y la cuota incluida va de 5 GB a 250 GB según el plan. Para probarlo, genera las claves S3 en el panel, define S3_ENDPOINT y S3_REGION=auto y ejecuta el ejemplo contra el bucket private. Conoce el Blob Storage y revisa la cuota de cada plan en Precios.

Blob Storage

Object storage compatible con S3, sin tarifas de salida

Más información

Preguntas frecuentes

¿Cuánto dura una URL prefirmada?

Depende del storage y de cómo se firmó la URL. En Amazon S3, el máximo es de 7 días con el SDK o la CLI y credenciales de usuario IAM, y de 12 horas desde la consola. Con credenciales temporales, la URL expira junto con ellas.

¿Se puede cancelar una URL prefirmada antes de que expire?

En general no. La URL sigue siendo válida mientras lo sean su firma y las credenciales que la crearon. Si necesitas revocar el acceso, usa un enlace para compartir revocable o un plazo muy corto.

¿Cualquiera con la URL puede descargar el archivo?

Sí. La URL prefirmada funciona como un token al portador: quien la tenga accede al archivo hasta que expire. Trátala como una contraseña temporal y no la publiques en lugares abiertos.

¿La URL prefirmada sirve para subir archivos?

Sí. Generas una URL para el método PUT y el navegador o la app del usuario envía el archivo directo al storage, sin pasar por tu servidor.

Siguiente artículoQué es el almacenamiento de objetosEl almacenamiento de objetos guarda archivos como objetos con clave y metadatos, accesibles por una API HTTP. Mira cómo funciona, para qué sirve y sus límites.

Más en Storage

Ver los 15 artículos