Proxy de imágenes
Usa el proxy de imágenes de Nowly cuando Discord no pueda cargar directamente una imagen de presencia desde un CDN externo compatible.
Para qué sirve
El proxy de imágenes está pensado para un caso concreto: una presencia puede ver una imagen pública en la página, pero Discord no puede cargarla de forma fiable desde la URL original.
Es útil para miniaturas de vídeo, avatares, pósters o imágenes de categoría servidas por un CDN externo cuando:
- la imagen es pública y ya está visible en el navegador;
- la URL del CDN es demasiado larga para Discord Rich Presence;
- Discord rechaza, deja expirar o no puede descargar la imagen directa;
- la presencia necesita mostrar una imagen del contenido en lugar de usar solo el logo del servicio.
No es un proxy de imágenes genérico. La API solo acepta servicios y dominios permitidos explícitamente.
Cómo funciona
El flujo recomendado usa una URL corta temporal:
TXTPOST https://api.nowly.me/images-proxy
GET https://api.nowly.me/images-proxy/<id>La presencia envía a la API la URL CDN real de la imagen. La API comprueba que el servicio esté permitido, descarga la imagen, valida su tipo MIME y su tamaño, y la guarda temporalmente en caché. Después devuelve una URL corta como:
TXThttps://api.nowly.me/images-proxy/abc123...Esa URL devuelve directamente los bytes de la imagen con el Content-Type correcto. Está pensada para largeImageKey o smallImageKey.
import { createCachedImageProxyUrl } from "@nowly/sdk"
const image = await createCachedImageProxyUrl("tiktok", imageUrl)
await presence.setActivity({
details: "Watching a video",
largeImageKey: image ?? Assets.Logo,
})La caché es corta, actualmente cinco minutos. El helper también mantiene una caché en memoria dentro de la presencia para no llamar a la API en cada actualización.
Endpoint directo
El proxy directo anterior sigue disponible para pruebas manuales o URL que ya sean suficientemente cortas:
TXThttps://api.nowly.me/image-proxy?service=<service>&url=<url-codificada>
https://api.nowly.me/i?u=<url-codificada>Los parámetros url y u deben codificarse con encodeURIComponent. Para Discord Rich Presence, prefiere createCachedImageProxyUrl, porque Discord limita las claves de imagen a 300 caracteres.
Configuración en una presencia
Primero, extrae la URL real de la imagen desde la página:
const getPoster = (video: HTMLVideoElement): string | undefined => {
if (video.poster) return video.poster
const image = video.closest("[data-video]")?.querySelector("img")
return image?.getAttribute("src") ?? undefined
}Después, pasa esa URL por el helper antes de definir la actividad:
import { createCachedImageProxyUrl } from "@nowly/sdk"
const poster = await createCachedImageProxyUrl("tiktok", getPoster(video))
await presence.setActivity({
details: "Watching a video",
largeImageKey: poster ?? Assets.Logo,
})Mantén siempre un recurso de respaldo. Si la página no tiene imagen, la imagen es demasiado pesada o el origen no está permitido, la presencia debe seguir funcionando con Assets.Logo o un recurso local.
Añadir un servicio
Los dominios permitidos se validan en la API, no en la presencia - una presencia no puede proxificar un dominio arbitrario solo con pedirlo en tiempo de ejecución. No hay un paso de aprobación aparte ni cambios de código en la API: declaras directamente los hosts que tu presencia necesita en su propio metadata.json, usando el mismo service (el slug de tu presencia) que ya pasas al helper:
"imageProxy": {
"hostSuffixes": ["netflix.com", "nflxvideo.net", "nflximg.net"],
"headers": { "Referer": "https://www.netflix.com/" }
}Esto se publica en la API automáticamente, igual que el resto de tu metadata.json. La API solo confía en esto para el service id de tu propia presencia: una presencia no puede declarar nombres de host en nombre de otra, y una solicitud solo se permite si el hostname de la URL destino coincide realmente con alguno de los sufijos declarados.
Cuando tu PR toca imageProxy, el bot de vista previa de presencias lo detecta automáticamente, añade una sección Image Proxy Requested a su comentario listando los nombres de host declarados, y aplica una etiqueta image-proxy. Un revisor debe confirmar igualmente que esos nombres de host son públicos y seguros de proxificar antes de fusionar - explica en tu PR por qué Discord no puede usar la URL directa y qué imagen verá el usuario.
Límites y seguridad
El proxy solo sirve imágenes públicas cuyos hosts hayan sido declarados por una presencia revisada. Rechaza URL que no sean HTTPS, hosts que no coincidan con ningún sufijo declarado, respuestas que no sean imágenes y archivos demasiado grandes.
Los propios endpoints son públicos y no requieren autenticación (las presencias los llaman directamente desde el navegador, así que no hay ningún secreto que adjuntar) y comparten el límite de tasa global de la API - no hay una cuota dedicada por presencia. No lo uses para contenido de cuentas privadas, recursos autenticados, URL de tracking, entradas arbitrarias del usuario o contenido que no sea una imagen.