---
name: comfyui_fetch_civitai_image_meta
kind: function
lang: py
domain: ml
version: "1.0.0"
purity: impure
signature: "def comfyui_fetch_civitai_image_meta(image_ref, token: str | None = None, timeout: float = 15.0) -> dict"
description: "Recupera los detalles de generacion de una imagen de Civitai por su id o URL (civitai.com/images/<id>): prompt, prompt negativo, modelo, sampler, steps, cfg, seed, dimensiones, recursos (checkpoint + LoRAs) y nivel NSFW. Es el paso 'entrar al link y observar como lo hicieron'. Usa los endpoints tRPC image.getGenerationData + image.get que consume la propia web de civitai.com, porque la API v1 publica (GET /api/v1/images) hoy devuelve meta=null y un JPEG recomprimido sin workflow embebido. Si la meta trae un workflow ComfyUI embebido (campo comfy) lo devuelve en API format. NO descarga la imagen ni reconstruye workflow: solo lee. Impura: HTTP a civitai.com + subprocess (pass para el token)."
tags: [comfyui, civitai, replicate, ml, metadata, http, stable-diffusion]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: ["json", "os", "re", "subprocess", "urllib.error", "urllib.parse", "urllib.request"]
params:
  - name: image_ref
    desc: "Id numerico de la imagen (int o str), o su URL 'https://civitai.com/images/<id>' (con o sin query string). Tambien acepta el path '/images/<id>'."
  - name: token
    desc: "API token de Civitai (header Authorization Bearer). Si None se resuelve de 'pass civitai/api-token'. No hardcodear. keyword-only."
  - name: timeout
    desc: "Timeout HTTP en segundos por peticion tRPC. keyword-only."
output: "dict {ok, image_id, meta, resources, process, comfy_workflow, width, height, nsfw, nsfw_level, post_id, url_uuid, page_url, error}. meta = dict de generacion estilo A1111/Civitai (prompt, negativePrompt, Model, sampler, steps, cfgScale, seed, Size, ...); {} si la imagen no expone datos. resources = lista de {modelType, modelName, ...}. comfy_workflow = workflow ComfyUI en API format si la meta lo trae embebido, {} si no. nsfw = bool derivado de nsfw_level (politica SFW del caller). ok=False con error si el id no se parsea, la red falla, o la imagen no tiene ni meta ni workflow embebido."
tested: true
tests:
  - "test_parse_image_id_acepta_int_str_url"
  - "test_parse_image_id_rechaza_invalidos"
  - "test_is_nsfw_niveles"
  - "test_extract_comfy_workflow_embebido_y_ausente"
test_file_path: "python/functions/ml/comfyui_fetch_civitai_image_meta_test.py"
file_path: "python/functions/ml/comfyui_fetch_civitai_image_meta.py"
---

## Ejemplo

```python
import sys, os
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
from ml.comfyui_fetch_civitai_image_meta import comfyui_fetch_civitai_image_meta

# "Entra al link y observa los detalles de cómo lo hicieron":
src = comfyui_fetch_civitai_image_meta("https://civitai.com/images/23526611")
print(src["ok"], src["nsfw"])                    # True False
print(src["meta"].get("sampler"), src["meta"].get("steps"))  # Euler 20
print([r["modelName"] for r in src["resources"]])            # ['FLUX']
```

## Cuando usarla

Cuando te pasen un link o id de una imagen de Civitai y necesites saber **cómo se generó**
(prompt, modelo, sampler, LoRAs) antes de replicarla, comparar recetas, o alimentar la
librería de skills. Es el primer paso del pipeline `comfyui_replicate_civitai_oneshot`. Para
buscar imágenes por modelo/feed usa `comfyui_search_civitai_images`; esta función resuelve UNA
imagen concreta por id.

## Gotchas

- Usa endpoints tRPC **no documentados** de Civitai (`image.getGenerationData`, `image.get`).
  Son los que usa la web y hoy funcionan, pero pueden cambiar sin aviso (frágil por diseño;
  no hay alternativa pública que dé la meta por id).
- Civitai responde **HTTP 500** para un id inexistente o privado → la función devuelve
  `ok=False` con el mensaje. Imágenes antiguas o subidas sin receta pueden devolver `meta={}`.
- El token sale de `pass civitai/api-token`. Sin token algunas imágenes gated no resuelven.
- `comfy_workflow` (workflow embebido) hoy rara vez viene por esta vía; lo normal es
  reconstruir desde `meta` con `comfyui_map_a1111_params`.
- El `meta` está en formato A1111 (claves `Model`, `cfgScale`, `Size`), no ComfyUI. Tradúcelo
  con `comfyui_map_a1111_params`.
