Model Metadata Extractor
Read a model file's metadata without ever trusting it
- metadata_json
- model_kind
- total_params
- fingerprint
- lineage_json
Every model you pull from CivitAI or a random HuggingFace link is a file that, the moment ComfyUI loads it, gets to run code in your Python process. Old .ckpt and .pt files are literally pickle archives - Python's "pick up this object graph and rebuild it" format, which is also the ecosystem's standing remote-code-execution vector. You usually don't think about that until the second time you download a checkpoint from somewhere sketchy. This node is the move you want between "downloaded" and "loaded": a metadata reader that inspects a model file without loading it, so you can see what you're about to run before you run it.
Model Metadata Extractor (MEC) takes an absolute path to a .safetensors, .pt, .pth, or .ckpt and reports what's inside. The mechanism is where the safety promise lives, and it's worth understanding so you trust it the right amount. For .safetensors it reads the JSON header at the front of the file - that format was designed exactly for this, metadata up front, tensors behind it. For modern PyTorch saves (which are actually ZIP archives) it lists the archive members with zipfile and reads the sizes. For legacy pickle files it does not unpickle them; it runs pickletools.dis over the raw bytes to enumerate the top-level opcodes safely, with no globals imported and no objects constructed. In other words: it can tell you a checkpoint is 2.3 billion parameters and carries a CivitAI training tag without ever executing a byte of it.
What you get out
The output that matters for most people is total_params (summed across every tensor - the fastest sanity check that the LoRA you downloaded is actually a LoRA and not something pretending to be one) and model_kind, which classifies the file as checkpoint, lora, vae, controlnet, or unknown. metadata_json dumps the full header, including any training tags baked in by the trainer - the modern torch-zip format stores those as plain data. lineage_json surfaces license and provenance fields when the metadata has them.
A fingerprint that's fast on purpose
The fifth output, fingerprint, is the quiet sleeper. It's a SHA256 over (file size, first 1 MB, last 1 MB) - not the whole file, so it's effectively instant even on a 7 GB model. That's a perfectly good cache key: same file in, same fingerprint out, and two copies of the same checkpoint hash identically while a re-export doesn't. The author calls it "far faster than full-file hashing" and that's the honest pitch.
Install
Setup is just the pack install - clone Code2Collapse/ComfyUI-CustomNodePacks into ComfyUI/custom_nodes (or search "CustomNodePacks" in ComfyUI Manager), restart, and it's under C2C/Diagnostics. No model downloads, no GPU, nothing to fetch. It runs on a plain string input, so you can even wire a file_path from another node.
The honest caveat
One honest caveat: "safe to run on untrusted files" means it won't execute the weights. It can't tell you the checkpoint is benign, only that the header looks like a checkpoint. Treat it as the inspection step, not the security boundary. And the file_path input is an absolute path on disk - ComfyUI's usual file-picker won't populate it, so you'll be typing or pasting paths. Small friction, worth it for knowing what you're about to load.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| file_path | STRING | Absolute path to a model file (.safetensors / .pt / .pth / .ckpt). | |
| compute_fingerprintopt | BOOLEAN | true | Compute SHA256 over (size, first 1 MB, last 1 MB). Suitable cache key; far faster than full-file hashing. |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| metadata_json | STRING | Full metadata as JSON (header fields, training tags, format). |
| model_kind | STRING | Detected model kind (e.g. checkpoint, lora, vae, controlnet, unknown). |
| total_params | INT | Total parameter count summed across all tensors. |
| fingerprint | STRING | SHA256 fingerprint over (size, first 1 MB, last 1 MB) when enabled. |
| lineage_json | STRING | License + lineage information as JSON when present in metadata. |