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; use GET /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 onlyGET /api/search?q={query} returns {packages: [{package: "name"}]}, not descriptions. You need a second GET /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 — the versions array in the package API response lists from oldest to newest. Use the top-level latest object for current version data, not versions[-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 correct version string and the correctly-encoded archive_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 APIGET /api/packages/{name}/score returns grantedPoints, maxPoints, likeCount, downloadCount30Days, and a full tags[] array. Don't rely on the browser /score tab — use the API endpoint.
  • Security advisories ARE available via APIGET /api/packages/{name}/advisories returns 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

PageURL PatternNotes
Homepagehttps://pub.dev/Search form, trending/new packages
Browser searchhttps://pub.dev/packages?q={query}Disallowed by robots.txt — use API instead
Package readmehttps://pub.dev/packages/{name}Default tab — readme content
Package changeloghttps://pub.dev/packages/{name}/changelogVersion history prose
Package installhttps://pub.dev/packages/{name}/installpubspec.yaml snippet + flutter/dart commands
Package versionshttps://pub.dev/packages/{name}/versionsAll versions with download links
Package examplehttps://pub.dev/packages/{name}/exampleExample code tab
Package scorehttps://pub.dev/packages/{name}/scorepub points breakdown
Publisherhttps://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=1Returns names only
Archive downloadhttps://pub.dev/api/archives/{name}-{version}.tar.gzDirect package download

Page Structures

Homepage

ElementSelectorNotes
Search formform.search-barWraps the search input
Search inputinput[name="q"]Also: input[type="search"], input[title="Search"]
Sign in#-account-loginGoogle OAuth
Package name links (listings)a.mini-list-item-title22 matches on homepage — package cards
Publisher links (listings)a.publisher-link20 matches — publisher names on package cards
View All Flutter packagesa[href^="/packages?q=sdk%3Aflutter"]"VIEW ALL" link
View All Dart packagesa[href^="/packages?q=sdk%3Adart"]"VIEW ALL" link
View All trendinga[href^="/packages?sort=trending"]"VIEW ALL" link

Package Detail (/packages/{name})

ElementSelectorNotes
Tab navigationul.detail-tabs-headerContains all 5 tab links
Tab: Readmea[href="/packages/{name}"]Default tab
Tab: Changeloga[href="/packages/{name}/changelog"]
Tab: Installinga[href="/packages/{name}/install"]pubspec.yaml snippet
Tab: Versionsa[href="/packages/{name}/versions"]
Tab: Examplea[href="/packages/{name}/example"]May be absent if no example
Active tab contentsection.tab-contentAlso: section.tab-content.detail-tab-readme-content on readme tab
Metadata sidebaraside.detail-info-boxPublisher, score, platforms, topics, dependencies
Like buttonbutton[title="Like this package"]Requires login to function
Dart SDK badgea[href^="/packages?q=sdk%3Adart"]Shown if Dart-compatible
Flutter SDK badgea[href^="/packages?q=sdk%3Aflutter"]Shown if Flutter-compatible
Platform badgesa[href^="/packages?q=platform%3Aandroid"] etc.Android, iOS, Linux, macOS, Web, Windows
Topic tagsa.topics-tagMultiple matches — each links to topic search
Publisher linka[href^="/publishers/"]In sidebar — 3 matches (sidebar repeats)

Versions Page (/packages/{name}/versions)

ElementSelectorNotes
Versions tab contentsection.tab-content.detail-tab-versions-contentWraps full version list
Version page linka[title="Visit {name} {version} page"]e.g. "Visit http 1.6.0 page"
Version archive downloada[title="Download {name} {version} archive"]Direct .tar.gz link
Version docs linka[title="Go to the documentation of {name} {version}"]Not all versions have docs
Atom feeda[href^="/api/packages"]Versions feed link

Navigation Flows

Flow: Search for a Package [API] (Recommended)

Starting point: None — direct HTTP fetch Prerequisites: None

StepActionTargetNotes
1fetchhttps://pub.dev/api/search?q={query}&page=1Returns package names only
2readpackages[].packageArray of name strings
3fetchhttps://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 next field present → paginate: GET https://pub.dev/api/search?q={query}&page=2

Flow: Search via Browser [Browser]

Starting point: https://pub.dev/ Prerequisites: None

StepActionTargetValueWait ForTimeout
1navigatehttps://pub.dev/input[name="q"] visible5s
2typeinput[name="q"]Search term
3pressinput[name="q"]EnterURL contains /packages?q=3s
4reada.mini-list-item-titlePackage 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

StepActionTargetValueWait ForTimeout
1navigatehttps://pub.dev/packages/{name}section.tab-content visible5s
2readsection.tab-content, aside.detail-info-box, ul.detail-tabs-headerContent 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

StepActionTargetWait ForTimeout
1clicka[href="/packages/{name}/changelog"]New page loads3s
2readsection.tab-content

Tab URLs (navigate directly instead of clicking):

TabURL
Readmehttps://pub.dev/packages/{name}
Changeloghttps://pub.dev/packages/{name}/changelog
Installinghttps://pub.dev/packages/{name}/install
Versionshttps://pub.dev/packages/{name}/versions
Examplehttps://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

StepActionTargetNotes
1fetchhttps://pub.dev/api/packages/{name}No auth, no rate limit
2readlatest.version, latest.pubspec.description, latest.pubspec.environment.sdkCore 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:

FieldDescription
latest.versionCurrent stable version string
latest.pubspec.descriptionOne-line package description
latest.pubspec.environment.sdkDart SDK constraint (e.g. "^3.4.0")
latest.pubspec.dependenciesObject: dep name → version constraint
latest.pubspec.topics[]Topic tags (e.g. ["http", "network"])
latest.pubspec.repositorySource repository URL
latest.publishedISO 8601 publish timestamp
latest.archive_urlDirect download URL for the .tar.gz
versions[]Oldest first — full list; use latest for current
versions[].versionVersion string (may contain + for build metadata)
versions[].archive_urlDownload 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:

FieldDescription
grantedPointspub points earned (0–160)
maxPointsMaximum possible points (160)
likeCountTotal likes
downloadCount30DaysDownloads 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:

FieldDescription
advisories[]Array of OSV-format security advisories (empty array = no known CVEs)
advisories[].idGHSA identifier
advisories[].aliases[]CVE numbers
advisories[].summaryOne-line description
advisories[].database_specific.severityCRITICAL / HIGH / MODERATE / LOW
advisories[].affected[].ranges[].eventsintroduced and fixed version bounds
advisoriesUpdatedTimestamp 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}?"

  1. Fetch: GET https://pub.dev/api/packages/{name}
  2. Read latest.version
  3. Output the pubspec.yaml dependency line:
    dependencies:
      {name}: ^{latest.version}
    
  4. Read latest.pubspec.environment.sdk — check if the Dart SDK constraint is compatible with the user's Dart version
  5. Read latest.pubspec.dependencies — mention any notable transitive dependencies

Output: The pubspec.yaml snippet + Dart SDK requirement


"Find a package that does X"

  1. Fetch: GET https://pub.dev/api/search?q={X}&page=1
  2. Get top 3-5 package names from packages[].package
  3. Fetch all in parallel: GET https://pub.dev/api/packages/{name} for each
  4. Compare: latest.pubspec.description, latest.pubspec.topics[], latest.pubspec.environment.sdk
  5. 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}"

  1. Fetch all in parallel (4 calls total):
    • GET /api/packages/{pkg1} and GET /api/packages/{pkg2} — metadata
    • GET /api/packages/{pkg1}/score and GET /api/packages/{pkg2}/score — popularity + pub points
  2. Optionally also fetch in parallel:
    • GET /api/packages/{pkg1}/advisories and GET /api/packages/{pkg2}/advisories — security
  3. Compare from latest + score:
    • latest.version — current stable version
    • latest.published — recency
    • latest.pubspec.environment.sdk — Dart SDK requirement
    • latest.pubspec.dependencies — count of runtime dependencies
    • grantedPoints / maxPoints — pub points (code quality, docs, platform support)
    • downloadCount30Days — actual usage (most important popularity signal)
    • likeCount — community endorsement
  4. Check: advisories[].length > 0 — warn if unpatched CVEs exist for current version
  5. 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 for domcontentloaded after clicking a tab.
  • Version list is fully rendered: The /versions page lists all versions in the HTML — no pagination, no lazy loading. section.tab-content.detail-tab-versions-content contains the full list.
  • Readme is rendered Markdown: The readme tab content is server-rendered HTML from Markdown. Read section.tab-content for the full formatted content.

Timing & Waiting

TransitionWait ForTypical Delay
Page navigationdomcontentloaded0.5–2s
Tab click (changelog, install, etc.)domcontentloaded0.5–2s
Search submitURL changes to /packages?q=1–2s
JSON API fetchResponse body0.2–1s

Rate Limits

ScopeLimitNotes
JSON APINo documented limitVery permissive; CDN-backed
Browserrobots.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

  1. 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 call GET /api/packages/{name} separately for each result to get metadata.

  2. 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-level latest object for current version data.

  3. + in version numbers is URL-encoded in archive paths. Version 0.12.0+4 appears as + in the browser URL (/packages/http/versions/0.12.0+4) but as %2B in the archive URL (http-0.12.0%2B4.tar.gz). The API provides the correctly-encoded archive_url — use that directly rather than constructing the URL yourself.

  4. No Dart SDK field at the top level. Minimum Dart SDK is at latest.pubspec.environment.sdk, nested inside the pubspec object. There is no dart_sdk or min_sdk field at the package root.

  5. 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.

  6. robots.txt disallows browser search. Disallow: /packages?q= means well-behaved agents should not use the browser search results page. Use GET /api/search?q= for all search.

  7. 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.

  8. Score, downloads, and likes are NOT in the main package endpoint. GET /api/packages/{name} does not include grantedPoints, likeCount, or downloadCount30Days. These require a separate call to GET /api/packages/{name}/score. Always fetch /score in parallel when comparing packages.

  9. /score tags array encodes platform/SDK support. The tags[] in the /score response includes sdk: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] or versions[versions.length-1] for the latest version — the array is oldest-first. Use latest.version instead.
  • NEVER construct archive URLs by concatenating name + version — the + encoding is inconsistent. Use latest.archive_url or versions[i].archive_url from the API response directly.
  • NEVER use /packages?q= for automated search — disallowed by robots.txt. Use GET /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 /score endpoint for package comparisonsgrantedPoints, likeCount, and downloadCount30Days are available via GET /api/packages/{name}/score. This is a separate call from /api/packages/{name} — the main package endpoint does NOT include these fields.
  • NEVER skip /advisories for security-sensitive comparisonsGET /api/packages/{name}/advisories returns full CVE data in OSV format. An empty advisories[] array means no known vulnerabilities.

Freshness

Skill verified2026-02-20
API stable since2018 — /api/packages/{name}, /score, /advisories, /publisher all confirmed working 2026-02-20
Selector stabilityHIGH — server-rendered MPA with intentional class names (detail-info-box, detail-tabs-header, tab-content); no hashed classes
Breaking change riskLow — pub.dev is the official Dart registry; UI changes infrequent
v1.1.0 changesAdded /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