Use the OSV API when you check a handful of packages now and then. Use the bulk dumps in the osv-vulnerabilities bucket when you scan constantly, work offline, or want a local mirror that you refresh from a list of recently modified records. Many tools end up using both.
What the dumps contain
OSV aggregates advisories from many sources into one format and exports them to a public storage bucket. The documentation lists the full database as a single zip at gs://osv-vulnerabilities/all.zip, and says it includes withdrawn records. Each ecosystem also has its own zip, and each record is a JSON file at a predictable path under the ecosystem folder.
You can download over plain HTTP too. The documentation gives the PyPI example at storage.googleapis.com/osv-vulnerabilities/PyPI/all.zip. No account is needed for that path.
How to keep a mirror fresh
Re-downloading everything each hour is wasteful. OSV publishes modified_id.csv files for this reason. There is a top level file for all ecosystems and one inside each ecosystem folder.
The format is simple. Each line is an ISO timestamp, a comma, then the ecosystem folder and ID for the top level file, or only the ID for the per ecosystem files. The files are sorted newest first, so you read from the top and stop as soon as you reach a timestamp you have already processed.
2024-08-15T00:05:00Z,PyPI/PYSEC-2021-123
2024-08-15T00:01:00Z,Go/GO-2022-0123
Those two lines are the documentation's own example of the layout. Store the newest timestamp you handled, and next run, fetch only the IDs above it.
API or dump: a decision table
| Your situation | Better fit |
|---|---|
| A script checks one project at a time | API |
| A CI job runs thousands of times a day | Dump or mirror |
| The scanner runs in an air gapped network | Dump |
| You need the answer for one package right now | API |
| You want to search all records by your own rules | Dump |
The API has its own cost: every lookup depends on network access and on a service you do not run. A mirror has a different cost: you now own freshness, storage and parsing.
Things to watch
Withdrawn records are in the dumps. Treat a record with a withdrawn timestamp as retracted, not as current. Records without an ecosystem, usually withdrawn ones, go to a folder named [EMPTY], so a loop over ecosystem folders will miss them.
Ecosystem names can include a colon, such as Alpine:v3.17. The documentation says the dump always has a folder with the part before the colon removed, in this case Alpine, containing the advisories for all releases. It also says OSV has stopped exporting entries for ecosystems with prefixes, so check the ecosystem list file in the bucket instead of hardcoding names.
Also check each record's license. The documentation lists the source databases and their licenses, which range from CC BY 4.0 to CC0 to MIT, so your redistribution rules depend on which sources you keep.
Try it yourself
Click through it at your own pace, or open it full screen. Watch how a new advisory triggers a re-check of something you already shipped, which is the job a fresh mirror exists to do.
Where this fits
A mirror is only useful if something rescans old inventories when it updates. See rescanning stored SBOMs when a new advisory lands. Safeguard offers SBOM and dependency scanning, and the free scan lets you try it on a real project without building any of this.
Quick check
How do I download only what changed?
Read modified_id.csv from the top, newest first, and stop when you reach a timestamp you already processed. Fetch only those IDs.
Do the dumps include withdrawn advisories?
Yes. The full zip includes withdrawn records, so check the withdrawn field before treating a record as active.
Sources
Last reviewed: 19 October 2026.