Updated ยท Sources & corrections
In this guide
- Choose the download operation first
- A repository name, a revision and a checksum answer different questions
- Run a small pinned download and negative control
- Read failures before changing the expected digest
- Turn the example into a useful artifact record
- What this procedure establishes
- Record an adapter revision and a base revision separately
- Sources and verification scope
To make a Hugging Face download repeatable, select the repository and a full commit revision, use that same revision for every file from that repository, and record what you actually downloaded. A SHA-256 digest lets you compare later copies with your recorded bytes. It does not establish who created the model or whether you may use it.
This guide demonstrates the process with a small public BERT configuration file. It includes an executed download check and a deliberately changed local copy. You do not need a GPU or model weights to reproduce this example.
Choose the download operation first
| Need | Official Hub operation | Record |
|---|---|---|
| One known file | hf_hub_download | Repository, filename, full revision |
| A repository snapshot | snapshot_download | Repository, full revision, selected-file filters |
| A model object for inference | Your framework loader | Model and component revisions plus runtime dependencies |
The official download guide documents single-file and snapshot downloads. Its cache paths point to managed cached files: do not modify those files to run a corruption experiment. The example below uses an isolated temporary copy instead.
A repository name, a revision and a checksum answer different questions
The repository identifies the project. A branch such as main selects a state that can move. A full commit identifies the selected repository state. A file digest records particular bytes. Keep the repository identifier beside its revision; an adapter in another repository needs its own revision.
Do not treat one file digest as a checksum for a complete model. Configuration, tokenizer or processor assets, weight shards, adapter files and custom code are separate inputs. A successful check of config.json says nothing about unlisted files. Compatibility still needs application testing; our LoRA and QLoRA guide explains why a training-method choice is another distinct decision.
Run a small pinned download and negative control
Prerequisites: Python 3, HTTPS access to huggingface.co and permission to use a temporary directory. Save the following as verify_pinned_config.py and run python verify_pinned_config.py. It uses Python’s standard library, downloads only config.json, and removes its temporary copies on completion. It writes download-validation.json beside the script, so run it from a working folder where that result filename is available.
The repository below is google-bert/bert-base-uncased. The fixed revision is 86b5e0934494bd15c9632b12f734a8a67f723594. The digest is our recorded download result, rather than an independent publisher signature. The pinned repository view provides context for that selection.
"""Download one public pinned config to an isolated directory; no model loading."""
import hashlib,json,tempfile,urllib.request
from pathlib import Path
REPO='google-bert/bert-base-uncased'
REVISION='86b5e0934494bd15c9632b12f734a8a67f723594'
EXPECTED='7160e1553ad2ca51d8c1cb066be533db31826e12d173824c1bb0cb1a4f187d20'
url=f'https://huggingface.co/{REPO}/resolve/{REVISION}/config.json'
with urllib.request.urlopen(url,timeout=30) as response:
data=response.read(1024*1024+1)
if len(data)>1024*1024:raise ValueError('Unexpectedly large config')
actual=hashlib.sha256(data).hexdigest()
if actual!=EXPECTED:raise ValueError('Downloaded bytes differ from recorded example')
if json.loads(data)['model_type']!='bert':raise ValueError('Unexpected config')
with tempfile.TemporaryDirectory() as directory:
copied=Path(directory)/'config.json'
copied.write_bytes(data)
assert hashlib.sha256(copied.read_bytes()).hexdigest()==EXPECTED
copied.write_bytes(data+b'\n')
assert hashlib.sha256(copied.read_bytes()).hexdigest()!=EXPECTED
copied.unlink()
assert not copied.exists()
result={'repository':REPO,'revision':REVISION,'filename':'config.json','bytes':len(data),'sha256':actual,'checks':['download matches recorded digest','unchanged local copy matches','modified local copy differs','missing local copy detected'],'scope':'One config file; no weights, inference or authenticity attestation'}
Path(__file__).with_name('download-validation.json').write_text(json.dumps(result,indent=2),encoding='utf-8')
print(json.dumps(result,indent=2))
On 4 November 2026, the executed example downloaded 570 bytes with SHA-256 7160e1553ad2ca51d8c1cb066be533db31826e12d173824c1bb0cb1a4f187d20. All four recorded checks passed: the download matched the saved digest, an unchanged local copy matched, adding a newline changed the digest, and deleting the temporary copy left it absent. No model was loaded and no inference, weight verification or performance comparison was performed.
The changed copy may still parse as JSON. That is the point: JSON validity and byte identity are different checks. Python’s hashlib documentation describes the SHA-256 operation used here.
Read failures before changing the expected digest
| Result | Next check |
|---|---|
| HTTP 401 or 403 | Check repository visibility, gating and your authorized access. This public example should not require a token. |
| HTTP 404 | Check the repository, full revision and exact file path together. A path missing from one commit may exist in another. |
| Timeout or connection error | Check network access and retry deliberately. A failed request provides no file-integrity result. |
| Digest mismatch | Preserve the unexpected bytes separately and investigate the URL, selected revision and saved reference. Do not silently replace the expected digest. |
| Digest matches but application fails | Check component versions, tokenizer/config compatibility and the runtime. Matching bytes alone does not establish a working deployment. |
Turn the example into a useful artifact record
For your selected checkpoint, record the canonical repository identifier, full revision, each selected file path, size and SHA-256, retrieval date, the source of the expected digest, and the download client version. Add the tokenizer or processor repository and revision if separate. Keep the model card and licence at the revision you reviewed. File filters and intentionally omitted files belong in the record too.
A manifest you generate after a download is a baseline for detecting later differences. If that manifest is replaced along with the files, comparing them may reveal nothing. Store and review the reference separately according to your own release process. This tutorial does not implement signatures, provenance attestation or a complete supply-chain verifier.
When updating a checkpoint, compare the old and new records and run the tests relevant to your task before adopting the new revision. Keep permission assessment separate: open weights, open source and licence conditions explain why downloading a public file is not sufficient evidence of unrestricted reuse.
What this procedure establishes
It makes the selected file version explicit and demonstrates how a later copy can be compared with a recorded reference. A complete deployment also needs component compatibility checks, dependency records and review of any executable code. Begin with the smallest required artifact, record its identity, and expand the inventory to cover every input your application actually loads.
Record an adapter revision and a base revision separately
When an application loads a PEFT adapter from another repository, record two repository IDs and two revisions. The adapter commit identifies the adapter files. The base commit identifies the checkpoint those files are intended to modify. Check the adapter configuration and training records for the base revision before treating the pair as reproducible.
For example, the pinned configuration inspected on November 7, 2026 names meta-llama/Llama-3.2-3B-Instruct and has revision: null. Record the base revision as unknown unless the publisher or your training records identify it. A fresh lookup of the base repository can identify what you download today, while the training-time revision may remain unknown. See the PEFT checkpoint format for the configuration fields.
Sources and verification scope
AI Models News reviewed the official Hub download documentation and Python hashing reference on 4 November 2026. The exact public config download and temporary-copy checks above were executed; broader model or framework behavior was not tested. The illustration is generated editorial artwork. See our editorial policy.