NuGet Server API
|
This section documents MSBuild 18.9, the .NET SDK 10.0.402 (with its This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The C# Reference bibliography lists the reference material consulted while preparing these pages. |
Every NuGet client speaks the same HTTP protocol to every feed. Knowing its shape helps when debugging a private feed,
writing a mirror or a script, or reading a restore log full of URLs. This page explores the V3 protocol with curl
against nuget.org and a local BaGetter 1.6.5, on 2026-10-23. Hosting a feed is covered on
Private Feeds.
The service index
A source URL is the address of a service index: a JSON document listing resources, each with a type and a URL. Clients look up the resource type they need and never construct other URLs themselves.
curl -s https://api.nuget.org/v3/index.json | jq -r '.version, (.resources | length)'
3.0.0
40
Some of nuget.org’s resources (one entry per type; most types appear several times, with versions such as
/3.0.0-rc, or for redundant hosts):
SearchQueryService https://azuresearch-usnc.nuget.org/query
SearchAutocompleteService https://azuresearch-usnc.nuget.org/autocomplete
RegistrationsBaseUrl https://api.nuget.org/v3/registration5-semver1/
PackageBaseAddress/3.0.0 https://api.nuget.org/v3-flatcontainer/
LegacyGallery https://www.nuget.org/api/v2
PackagePublish/2.0.0 https://www.nuget.org/api/v2/package
SymbolPackagePublish/4.9.0 https://www.nuget.org/api/v2/symbolpackage
RepositorySignatures/4.7.0 https://api.nuget.org/v3-index/repository-signatures/4.7.0/index.json
VulnerabilityInfo/6.7.0 https://api.nuget.org/v3/vulnerabilities/index.json
Catalog/3.0.0 https://api.nuget.org/v3/catalog0/index.json
ReadmeUriTemplate/6.13.0 https://api.nuget.org/v3-flatcontainer/{lower_id}/{lower_version}/readme
(The listing was produced with a short Python filter instead of jq.) The version suffix of a type is the protocol
version of that resource, often the NuGet client version that introduced it; a client picks the newest type it
understands. BaGetter’s index is much smaller — publish, symbol publish, search, autocomplete, registrations and
package base address:
PackagePublish/2.0.0 http://localhost:5555/api/v2/package
SymbolPackagePublish/4.9.0 http://localhost:5555/api/v2/symbol
SearchQueryService http://localhost:5555/v3/search
RegistrationsBaseUrl http://localhost:5555/v3/registration/
PackageBaseAddress/3.0.0 http://localhost:5555/v3/package/
SearchAutocompleteService http://localhost:5555/v3/autocomplete
That is enough for restore, push and search; without VulnerabilityInfo it cannot feed NuGetAudit, which is why a
private-only configuration needs auditSources
(Auditing Packages for Vulnerabilities).
The resources restore uses
Package base address ("flat container") — the simplest resource and the one restore uses most: a version list
per lower-cased ID, and the .nupkg itself. These are the GET lines of a restore log
(How Package Installation Works):
curl -s https://api.nuget.org/v3-flatcontainer/humanizer.core/index.json
curl -s -o /dev/null -w '%{http_code} %{content_type}\n' https://api.nuget.org/v3-flatcontainer/humanizer.core/2.14.1/humanizer.core.2.14.1.nupkg
curl -s -o /dev/null -w '%{http_code}\n' https://api.nuget.org/v3-flatcontainer/humanizer.core/9.9.9/humanizer.core.9.9.9.nupkg
{"versions":["2.0.0-beta02-0092","2.0.0","2.0.1", … ,"3.0.1","3.0.8","3.0.10"]} (32 versions)
200 application/octet-stream
404
Registrations — per-package metadata (dependencies per framework, listing state, deprecation, vulnerabilities)
in pages; the registration5-gz-semver2 variant is gzip-compressed and includes SemVer 2.0.0 versions. Its index for
humanizer.core had one page covering 2.0.0-beta02-0092 to 3.0.10.
Search and autocomplete — what dotnet package search and the Visual Studio Browse tab call:
curl -s 'https://azuresearch-usnc.nuget.org/query?q=packageid:Humanizer.Core&take=1'
returned one hit, Humanizer.Core 3.0.10, with "verified": true (a reserved ID prefix).
Vulnerability information
VulnerabilityInfo/6.7.0 points to an index of two files — a periodically rebuilt base and an update with
everything since:
curl -s --compressed https://api.nuget.org/v3/vulnerabilities/index.json
[{"@name":"base","@id":"https://api.nuget.org/v3-vulnerabilities/2026.10.19.23.33.13/vulnerability.base.json","@updated":"2026-10-19T23:33:13.4608684Z","comment":"The base data for vulnerability update periodically"},
{"@name":"update","@id":"https://api.nuget.org/v3-vulnerabilities/2026.10.19.23.33.13/2026.10.23.11.33.39/vulnerability.update.json","@updated":"2026-10-23T11:33:39.4634622Z","comment":"The patch data for the vulnerability. Contains all the vulnerabilities since base was last updated."}]
The response is served with Content-Encoding: gzip regardless of the request’s Accept-Encoding; without
--compressed, curl saved the raw gzip bytes (505 bytes uncompressed). Clients download these two files once and
check every package locally — the audit sends no package IDs to the server.
Source: Vulnerability info: Index, Vulnerability page.
Publishing, status codes and limits
-
Publish —
PUTof the.nupkgto thePackagePublishURL with the API key in theX-NuGet-ApiKeyheader (dotnet nuget push);DELETEto unlist. Symbol packages go toSymbolPackagePublish. nuget.org returns409 Conflictfor an existing version (Publishing to nuget.org). -
Status codes —
200/201/202success,404not found (a missing version, as above),401/403authentication,409conflict,429rate limited. For any 5xx or network error the official client retries three times. -
Authentication — reads are anonymous on nuget.org; private feeds use basic authentication or tokens through credential providers (Authenticated Feeds and Credential Providers).
-
Rate limits — nuget.org’s V3 search is not rate-limited; the V1/V2 search and package endpoints are, per IP address (
429with "Rate limit is exceeded. Try again in N seconds."), and push and unlist have their own limits.
V2, the OData protocol at https://www.nuget.org/api/v2, still answers for old clients (nuget.exe 2.x and some
tools) but is deprecated; new feeds and scripts should use V3 only.
Common mistakes
-
Hard-coding
v3-flatcontainerURLs — read them from the service index; private feeds use other paths. -
Upper-case IDs or versions in flat-container URLs — they are lower-cased.
-
Scripting against V2 — deprecated and rate-limited.
-
Fetching the vulnerability files without decompressing — they are gzip-encoded.