pub-dev
Use when finding Dart or Flutter packages, checking pub scores, comparing versions, or reading package docs. Provides API and navigation flows for pub.dev.
pub.dev — Dart & Flutter Package Registry
Overview
Covers the full read workflow on pub.dev: searching for packages, reading package detail pages (readme, changelog, install instructions), browsing version history, and retrieving metadata via the JSON API. The JSON API is the recommended path for automation — returns full pubspec.yaml data including dependencies, SDK constraints, and topics.
Not covered here: Publishing packages, managing publishers, account settings, admin actions.
Auth required for: Publishing, liking packages, managing publishers. All browsing and search are public.
Agent Paths
Programmatic [API] — No browser needed
- Search (returns names only):
GET https://pub.dev/api/search?q={query}&page=1 - Package metadata + all versions:
GET https://pub.dev/api/packages/{name} - Score, likes, downloads:
GET https://pub.dev/api/packages/{name}/score - Security advisories:
GET https://pub.dev/api/packages/{name}/advisories - Publisher info:
GET https://pub.dev/api/packages/{name}/publisher - Download archive:
GET https://pub.dev/api/archives/{name}-{version}.tar.gz
Required headers: None — all public endpoints are open
Browser [Browser] — Requires browser control
- Use selectors and Navigation Flows below
- Required when: reading the rendered readme, browsing the changelog, viewing install instructions with copy-paste commands, or interacting with a logged-in account
When to use which
- Default to Programmatic if you know the package name — one call returns everything including all versions and full pubspec
- Use Browser when: the task involves reading formatted readme content, or the user wants to copy the pubspec.yaml dependency line from the UI
- Avoid
/packages?q=browser search — robots.txt disallows it for bots; useGET /api/search?q=instead
Agent Knowledge Note
Most frontier LLMs have pub.dev structure in training data. This skill adds value via:
- Search API returns names only —
GET /api/search?q={query}returns{packages: [{package: "name"}]}, not descriptions. You need a secondGET /api/packages/{name}call to get the description, version, or any metadata. This surprises agents expecting a rich search response like PyPI's. versions[]is oldest-first — theversionsarray in the package API response lists from oldest to newest. Use the top-levellatestobject for current version data, notversions[-1]. Agents commonly get this wrong.+in version numbers — Dart uses+for build metadata (e.g.,0.12.0+4). In browser URLs this stays as+(/packages/http/versions/0.12.0+4), but in archive URLs it's percent-encoded (http-0.12.0%2B4.tar.gz). The API response provides both the correctversionstring and the correctly-encodedarchive_url.- No Dart SDK version in a dedicated field — the minimum Dart SDK version is nested at
latest.pubspec.environment.sdk(a constraint string like"^3.4.0"), not a top-level field. - Popularity data IS available via API —
GET /api/packages/{name}/scorereturnsgrantedPoints,maxPoints,likeCount,downloadCount30Days, and a fulltags[]array. Don't rely on the browser/scoretab — use the API endpoint. - Security advisories ARE available via API —
GET /api/packages/{name}/advisoriesreturns the full OSV-format advisory list with GHSA IDs, CVEs, severity, and affected version ranges. - robots.txt disallows browser search URL —
/packages?q=is disallowed. The API search endpoint/api/search?q=is not disallowed and is the correct path.
Site Map
| Page | URL Pattern | Notes |
|---|---|---|
| Homepage | https://pub.dev/ | Search form, trending/new packages |
| Browser search | https://pub.dev/packages?q={query} | Disallowed by robots.txt — use API instead |
| Package readme | https://pub.dev/packages/{name} | Default tab — readme content |
| Package changelog | https://pub.dev/packages/{name}/changelog | Version history prose |
| Package install | https://pub.dev/packages/{name}/install | pubspec.yaml snippet + flutter/dart commands |
| Package versions | https://pub.dev/packages/{name}/versions | All versions with download links |
| Package example | https://pub.dev/packages/{name}/example | Example code tab |
| Package score | https://pub.dev/packages/{name}/score | pub points breakdown |
| Publisher | https://pub.dev/publishers/{domain} | e.g. /publishers/dart.dev |
| JSON API (package) | https://pub.dev/api/packages/{name} | Full metadata + all versions |
| JSON API (search) | https://pub.dev/api/search?q={query}&page=1 | Returns names only |
| Archive download | https://pub.dev/api/archives/{name}-{version}.tar.gz | Direct package download |
Page Structures
Homepage
| Element | Selector | Notes |
|---|---|---|
| Search form | form.search-bar | Wraps the search input |
| Search input | input[name="q"] | Also: input[type="search"], input[title="Search"] |
| Sign in | #-account-login | Google OAuth |
| Package name links (listings) | a.mini-list-item-title | 22 matches on homepage — package cards |
| Publisher links (listings) | a.publisher-link | 20 matches — publisher names on package cards |
| View All Flutter packages | a[href^="/packages?q=sdk%3Aflutter"] | "VIEW ALL" link |
| View All Dart packages | a[href^="/packages?q=sdk%3Adart"] | "VIEW ALL" link |
| View All trending | a[href^="/packages?sort=trending"] | "VIEW ALL" link |
Package Detail (/packages/{name})
| Element | Selector | Notes |
|---|---|---|
| Tab navigation | ul.detail-tabs-header | Contains all 5 tab links |
| Tab: Readme | a[href="/packages/{name}"] | Default tab |
| Tab: Changelog | a[href="/packages/{name}/changelog"] | |
| Tab: Installing | a[href="/packages/{name}/install"] | pubspec.yaml snippet |
| Tab: Versions | a[href="/packages/{name}/versions"] | |
| Tab: Example | a[href="/packages/{name}/example"] | May be absent if no example |
| Active tab content | section.tab-content | Also: section.tab-content.detail-tab-readme-content on readme tab |
| Metadata sidebar | aside.detail-info-box | Publisher, score, platforms, topics, dependencies |
| Like button | button[title="Like this package"] | Requires login to function |
| Dart SDK badge | a[href^="/packages?q=sdk%3Adart"] | Shown if Dart-compatible |
| Flutter SDK badge | a[href^="/packages?q=sdk%3Aflutter"] | Shown if Flutter-compatible |
| Platform badges | a[href^="/packages?q=platform%3Aandroid"] etc. | Android, iOS, Linux, macOS, Web, Windows |
| Topic tags | a.topics-tag | Multiple matches — each links to topic search |
| Publisher link | a[href^="/publishers/"] | In sidebar — 3 matches (sidebar repeats) |
Versions Page (/packages/{name}/versions)
| Element | Selector | Notes |
|---|---|---|
| Versions tab content | section.tab-content.detail-tab-versions-content | Wraps full version list |
| Version page link | a[title="Visit {name} {version} page"] | e.g. "Visit http 1.6.0 page" |
| Version archive download | a[title="Download {name} {version} archive"] | Direct .tar.gz link |
| Version docs link | a[title="Go to the documentation of {name} {version}"] | Not all versions have docs |
| Atom feed | a[href^="/api/packages"] | Versions feed link |
Navigation Flows
Flow: Search for a Package [API] (Recommended)
Starting point: None — direct HTTP fetch Prerequisites: None
| Step | Action | Target | Notes |
|---|---|---|---|
| 1 | fetch | https://pub.dev/api/search?q={query}&page=1 | Returns package names only |
| 2 | read | packages[].package | Array of name strings |
| 3 | fetch | https://pub.dev/api/packages/{packages[0].package} | Get full metadata for top result |
Success state: JSON with name, latest.version, latest.pubspec.description.
Branching:
- If
packages[]is empty → no results; try broader search term - If
nextfield present → paginate:GET https://pub.dev/api/search?q={query}&page=2
Flow: Search via Browser [Browser]
Starting point: https://pub.dev/
Prerequisites: None
| Step | Action | Target | Value | Wait For | Timeout |
|---|---|---|---|---|---|
| 1 | navigate | — | https://pub.dev/ | input[name="q"] visible | 5s |
| 2 | type | input[name="q"] | Search term | — | — |
| 3 | press | input[name="q"] | Enter | URL contains /packages?q= | 3s |
| 4 | read | a.mini-list-item-title | — | Package results visible | — |
Success state: URL is https://pub.dev/packages?q={term} with a.mini-list-item-title result links visible.
Flow: View Package Detail [Browser]
Starting point: Any page or direct URL Prerequisites: None
| Step | Action | Target | Value | Wait For | Timeout |
|---|---|---|---|---|---|
| 1 | navigate | — | https://pub.dev/packages/{name} | section.tab-content visible | 5s |
| 2 | read | section.tab-content, aside.detail-info-box, ul.detail-tabs-header | — | Content loaded | — |
Success state: Package page with readme content in section.tab-content, metadata sidebar in aside.detail-info-box, and tab navigation in ul.detail-tabs-header.
Flow: Browse Package Tabs [Browser]
Starting point: https://pub.dev/packages/{name}
Prerequisites: None
| Step | Action | Target | Wait For | Timeout |
|---|---|---|---|---|
| 1 | click | a[href="/packages/{name}/changelog"] | New page loads | 3s |
| 2 | read | section.tab-content | — | — |
Tab URLs (navigate directly instead of clicking):
| Tab | URL |
|---|---|
| Readme | https://pub.dev/packages/{name} |
| Changelog | https://pub.dev/packages/{name}/changelog |
| Installing | https://pub.dev/packages/{name}/install |
| Versions | https://pub.dev/packages/{name}/versions |
| Example | https://pub.dev/packages/{name}/example |
Note: Tab clicks navigate to new URLs — this is not a JavaScript tab toggle. Content is server-rendered on each URL.
Flow: Get Package Metadata [API] (Recommended)
Starting point: None — direct HTTP fetch Prerequisites: None
| Step | Action | Target | Notes |
|---|---|---|---|
| 1 | fetch | https://pub.dev/api/packages/{name} | No auth, no rate limit |
| 2 | read | latest.version, latest.pubspec.description, latest.pubspec.environment.sdk | Core fields |
Success state: JSON with top-level keys name, latest, versions.
API Response Shapes
GET /api/packages/{name}
{
"name": "http",
"latest": {
"version": "1.6.0",
"pubspec": {
"name": "http",
"version": "1.6.0",
"description": "A composable, multi-platform, Future-based API for HTTP requests.",
"repository": "https://github.com/dart-lang/http/tree/master/pkgs/http",
"topics": ["http", "network", "protocols"],
"environment": {
"sdk": "^3.4.0"
},
"dependencies": {
"async": "^2.5.0",
"http_parser": "^4.0.0",
"meta": "^1.3.0",
"web": ">=0.5.0 <2.0.0"
},
"dev_dependencies": {
"test": "^1.21.2"
}
},
"archive_url": "https://pub.dev/api/archives/http-1.6.0.tar.gz",
"archive_sha256": "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412",
"published": "2025-11-10T18:27:56.434747Z"
},
"versions": [
{
"version": "0.2.7+0",
"pubspec": { "name": "http", "version": "0.2.7+0", "description": "..." },
"archive_url": "https://pub.dev/api/archives/http-0.2.7%2B0.tar.gz",
"archive_sha256": "cc4fedb...",
"published": "2012-11-30T20:40:39.500320Z"
}
]
}
Key fields:
| Field | Description |
|---|---|
latest.version | Current stable version string |
latest.pubspec.description | One-line package description |
latest.pubspec.environment.sdk | Dart SDK constraint (e.g. "^3.4.0") |
latest.pubspec.dependencies | Object: dep name → version constraint |
latest.pubspec.topics[] | Topic tags (e.g. ["http", "network"]) |
latest.pubspec.repository | Source repository URL |
latest.published | ISO 8601 publish timestamp |
latest.archive_url | Direct download URL for the .tar.gz |
versions[] | Oldest first — full list; use latest for current |
versions[].version | Version string (may contain + for build metadata) |
versions[].archive_url | Download URL with + encoded as %2B |
GET /api/search?q={query}&page=1
{
"packages": [
{ "package": "http" },
{ "package": "dio" },
{ "package": "chopper" }
],
"next": "https://pub.dev/api/search?q=http&page=2"
}
Note: Returns package names only. No description, version, or score. Call GET /api/packages/{name} for each result to get metadata.
GET /api/packages/{name}/score
{
"grantedPoints": 160,
"maxPoints": 160,
"likeCount": 8408,
"downloadCount30Days": 8609458,
"tags": [
"publisher:dart.dev",
"sdk:dart",
"sdk:flutter",
"platform:android",
"platform:ios",
"platform:linux",
"platform:macos",
"platform:web",
"platform:windows",
"is:null-safe",
"is:dart3-compatible",
"license:bsd-3-clause",
"topic:http"
]
}
Key fields:
| Field | Description |
|---|---|
grantedPoints | pub points earned (0–160) |
maxPoints | Maximum possible points (160) |
likeCount | Total likes |
downloadCount30Days | Downloads in the last 30 days |
tags[] | Derived tags: publisher, SDK support, platforms, licenses, topics |
GET /api/packages/{name}/advisories
{
"advisories": [
{
"id": "GHSA-4rgh-jx4f-qfcq",
"aliases": ["CVE-2020-35669"],
"summary": "http before 0.13.3 vulnerable to header injection",
"severity": [{ "type": "CVSS_V3", "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N" }],
"database_specific": {
"severity": "MODERATE",
"github_reviewed": true,
"cwe_ids": ["CWE-74"]
},
"affected": [{
"ranges": [{ "events": [{ "introduced": "0" }, { "fixed": "0.13.3" }] }]
}]
}
],
"advisoriesUpdated": "2024-04-28T09:27:57.869544Z"
}
Key fields:
| Field | Description |
|---|---|
advisories[] | Array of OSV-format security advisories (empty array = no known CVEs) |
advisories[].id | GHSA identifier |
advisories[].aliases[] | CVE numbers |
advisories[].summary | One-line description |
advisories[].database_specific.severity | CRITICAL / HIGH / MODERATE / LOW |
advisories[].affected[].ranges[].events | introduced and fixed version bounds |
advisoriesUpdated | Timestamp of last advisory sync |
GET /api/packages/{name}/publisher
{ "publisherId": "dart.dev" }
Returns just the publisher domain string. Empty publisherId means no verified publisher. Matches publisher:dart.dev tag in /score response.
Common Agent Tasks
"Add {package} to my project" / "What's the pubspec.yaml line for {package}?"
- Fetch:
GET https://pub.dev/api/packages/{name} - Read
latest.version - Output the pubspec.yaml dependency line:
dependencies: {name}: ^{latest.version} - Read
latest.pubspec.environment.sdk— check if the Dart SDK constraint is compatible with the user's Dart version - Read
latest.pubspec.dependencies— mention any notable transitive dependencies
Output: The pubspec.yaml snippet + Dart SDK requirement
"Find a package that does X"
- Fetch:
GET https://pub.dev/api/search?q={X}&page=1 - Get top 3-5 package names from
packages[].package - Fetch all in parallel:
GET https://pub.dev/api/packages/{name}for each - Compare:
latest.pubspec.description,latest.pubspec.topics[],latest.pubspec.environment.sdk - Prefer packages with shorter dependency lists and recent
latest.published
Output: Comparison table of name / description / Dart SDK req / dep count / last published
"Compare {pkg1} vs {pkg2}"
- Fetch all in parallel (4 calls total):
GET /api/packages/{pkg1}andGET /api/packages/{pkg2}— metadataGET /api/packages/{pkg1}/scoreandGET /api/packages/{pkg2}/score— popularity + pub points
- Optionally also fetch in parallel:
GET /api/packages/{pkg1}/advisoriesandGET /api/packages/{pkg2}/advisories— security
- Compare from
latest+ score:latest.version— current stable versionlatest.published— recencylatest.pubspec.environment.sdk— Dart SDK requirementlatest.pubspec.dependencies— count of runtime dependenciesgrantedPoints/maxPoints— pub points (code quality, docs, platform support)downloadCount30Days— actual usage (most important popularity signal)likeCount— community endorsement
- Check:
advisories[].length > 0— warn if unpatched CVEs exist for current version - Check
versions.length— more versions = more maintained history
Output: Side-by-side table of both packages including downloads, pub points, and advisory status
Dynamic Content Patterns
- Server-rendered MPA: All pages are fully server-rendered HTML. Use
domcontentloaded— no JS wait needed for content. - Tab clicks navigate to new URLs: Each tab (
/changelog,/install,/versions,/example) is a separate page load, not a JavaScript toggle. Always wait fordomcontentloadedafter clicking a tab. - Version list is fully rendered: The
/versionspage lists all versions in the HTML — no pagination, no lazy loading.section.tab-content.detail-tab-versions-contentcontains the full list. - Readme is rendered Markdown: The readme tab content is server-rendered HTML from Markdown. Read
section.tab-contentfor the full formatted content.
Timing & Waiting
| Transition | Wait For | Typical Delay |
|---|---|---|
| Page navigation | domcontentloaded | 0.5–2s |
| Tab click (changelog, install, etc.) | domcontentloaded | 0.5–2s |
| Search submit | URL changes to /packages?q= | 1–2s |
| JSON API fetch | Response body | 0.2–1s |
Rate Limits
| Scope | Limit | Notes |
|---|---|---|
| JSON API | No documented limit | Very permissive; CDN-backed |
| Browser | robots.txt disallows /packages?q= | Use API search instead |
Parallel requests: Safe to fire multiple API requests in parallel — commonly needed to enrich search results (fetch metadata for each of N names returned by the search API).
Common Gotchas
-
Search API returns names only.
GET /api/search?q={query}returns{packages: [{package: "name"}]}. There is no description, version, or score in this response. You must callGET /api/packages/{name}separately for each result to get metadata. -
versions[]is oldest-first. The array starts at the very first release (often from 2012–2014 for popular packages) and ends at the latest. Use the top-levellatestobject for current version data. -
+in version numbers is URL-encoded in archive paths. Version0.12.0+4appears as+in the browser URL (/packages/http/versions/0.12.0+4) but as%2Bin the archive URL (http-0.12.0%2B4.tar.gz). The API provides the correctly-encodedarchive_url— use that directly rather than constructing the URL yourself. -
No Dart SDK field at the top level. Minimum Dart SDK is at
latest.pubspec.environment.sdk, nested inside the pubspec object. There is nodart_sdkormin_sdkfield at the package root. -
Tab clicks are page loads, not toggles. Unlike PyPI where tabs are preloaded in the DOM, pub.dev tabs each navigate to a different URL. Always wait for a new page load after clicking a tab.
-
robots.txt disallows browser search.
Disallow: /packages?q=means well-behaved agents should not use the browser search results page. UseGET /api/search?q=for all search. -
Docs links only appear for versions that have documentation. Not every version in the versions list has a docs link (
a[title="Go to the documentation of..."]). Older versions and pre-releases often lack documentation. -
Score, downloads, and likes are NOT in the main package endpoint.
GET /api/packages/{name}does not includegrantedPoints,likeCount, ordownloadCount30Days. These require a separate call toGET /api/packages/{name}/score. Always fetch/scorein parallel when comparing packages. -
/scoretags array encodes platform/SDK support. Thetags[]in the/scoreresponse includessdk:dart,sdk:flutter,platform:android,is:null-safe,license:bsd-3-clause, etc. This is a reliable machine-readable way to check compatibility without parsing the browser page.
Anti-Patterns
- NEVER use
versions[-1]orversions[versions.length-1]for the latest version — the array is oldest-first. Uselatest.versioninstead. - NEVER construct archive URLs by concatenating name + version — the
+encoding is inconsistent. Uselatest.archive_urlorversions[i].archive_urlfrom the API response directly. - NEVER use
/packages?q=for automated search — disallowed by robots.txt. UseGET /api/search?q={query}. - NEVER expect description or version from the search API — it returns names only. You need a second API call per package.
- NEVER look for Dart SDK version in a top-level field — it's at
latest.pubspec.environment.sdk, buried inside the pubspec object. - NEVER skip the
/scoreendpoint for package comparisons —grantedPoints,likeCount, anddownloadCount30Daysare available viaGET /api/packages/{name}/score. This is a separate call from/api/packages/{name}— the main package endpoint does NOT include these fields. - NEVER skip
/advisoriesfor security-sensitive comparisons —GET /api/packages/{name}/advisoriesreturns full CVE data in OSV format. An emptyadvisories[]array means no known vulnerabilities.
Freshness
| Skill verified | 2026-02-20 |
| API stable since | 2018 — /api/packages/{name}, /score, /advisories, /publisher all confirmed working 2026-02-20 |
| Selector stability | HIGH — server-rendered MPA with intentional class names (detail-info-box, detail-tabs-header, tab-content); no hashed classes |
| Breaking change risk | Low — pub.dev is the official Dart registry; UI changes infrequent |
| v1.1.0 changes | Added /score, /advisories, /publisher endpoints with real response shapes; corrected false anti-pattern that claimed score was browser-only; updated Compare task to fetch popularity data |