Maven Central Artifact Versions, Dates and Upgrade Check
Pricing
from $1.40 / 1,000 artifact version reports
Maven Central Artifact Versions, Dates and Upgrade Check
Java and JVM dependency checks from the official Maven Central search index: every published version with its UTC release date, the newest release derived from those dates, how old a pinned version is and how many versions it is behind. Batch coordinates, keyword, group and class search.
Pricing
from $1.40 / 1,000 artifact version reports
Rating
0.0
(0)
Developer
Samat Makatov
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
Java and JVM dependency checks from the official Maven Central search index: every published version with its UTC release date, the newest release derived from those dates, how old a pinned version is and how many versions it is behind. Batch coordinates, keyword, group and class search.
Paste the coordinates from your pom.xml or build.gradle and get one row per artifact: the newest release with its
release date, the newest prerelease separately, the number of published versions, the date of the first release, the
releases of the last twelve months and the recent versions with dates — plus, when you pin a version, its release
date, its age in days, whether it is still current and how many releases you are behind. The source is the search
index of the Central Repository, run by Sonatype: no API key, no account, no proxy and no browser.
Use cases
- CI gate on stale pins: feed the gate the coordinates of your build file and fail the job when
versionsBehindorlatestVersionAgeDayscrosses your threshold. - Upgrade tickets with real dates: "we are 7 releases and 2 years behind on slf4j-api" instead of "there is a newer version", with the release date of every version in between.
- Dependency health review:
releasesLast365Days,firstReleasedAtandlatestVersionAgeDaystell you whether a library is still shipping before you adopt it. - Choosing between two libraries by release cadence: run both coordinate lists and compare the release history.
- Finding the artifact that contains a class: a build fails on a missing class —
c:ObjectMapperreturns the artifacts that ship it. - Vendor or monorepo inventory:
g:com.squareup.okhttp3lists every artifact id a group publishes, with the newest release of each. - Scheduled "what updated since yesterday": switch on
onlyNewand a daily schedule writes only the artifacts whose newest version, prereleases included, changed since the previous run.
Input
Every field is optional, but a run needs at least one coordinate or one search query.
| Field | Type | Default | Allowed values / notes |
|---|---|---|---|
coordinates | string[] | – | Up to 50 artifacts, one per line, as groupId:artifactId or groupId:artifactId:version. A version turns the row into an upgrade check. Spaces, surrounding quotes and a trailing :jar or @aar are ignored. See Coordinate forms. |
searchQueries | string[] | – | Up to 10 free-text searches against the same index, passed on exactly as typed. Plain words, or the index qualifiers of Search qualifiers (g:, a:, c:, fc:, tags:, …). |
searchMaxItems | integer | 20 | 1–200. Top N artifacts per search query. Every artifact kept is a billed row. |
searchHydrate | boolean | false | Off: a search hit is written from its index entry — group, artifact id, the index's own latest version (which can be an old prerelease), the version count and the date of that entry — and the row says versionsSource: "index". On: every hit also gets its version history read, so it carries dated versions and a derived newest release like a coordinate (versionsSource: "history"), at one extra request per hit. Coordinates always get the full history. |
includePrereleases | boolean | false | Off: alpha, beta, RC, milestone, snapshot, dev and preview versions stay out of latestVersion, isLatest, versionsBehind and newerVersions — they are still reported in latestAnyVersion and in recentVersions with prerelease: true. On: the newest version wins whatever it is called. See What counts as a prerelease. |
packaging | string | – (every packaging) | Keep only versions published with this packaging, e.g. aar for Android libraries or pom for parent and BOM artifacts. Free text with suggestions: case and a leading dot are ignored, and any packaging Central uses is accepted — see Packaging values. |
releasedSince | string | – | YYYY-MM-DD, UTC. Keep only artifacts whose newest release is on or after this date; recentVersions then lists only versions inside the window and versionsInWindow counts them. Artifacts filtered out are counted in the run status and are not written or billed. |
versionsLimit | integer | 10 | 0–200. How many recent versions go into recentVersions (and how many version strings into newerVersions). 0 leaves both arrays out; the counted fields are computed from the whole scanned history either way. |
maxVersionsScanned | integer | 400 | 50–2000. How deep into a history one run reads, newest first, in pages of 200 versions. When the cap cuts a history, the row says so in historyTruncated. |
onlyNew | boolean | false | Remember the newest version of every artifact written and, on the next run of the same actor or task, write only the artifacts whose newest version, prereleases included, has changed. The first run writes everything. See What counts as a change for onlyNew. |
maxItems | integer | 50 | 1–1000. Hard cap on the rows this run writes, and so on what it costs. Coordinates are written first, in the order you gave them, then search hits. |
fields | string[] | all | Keep only these columns, in this order. id, groupId, artifactId, found, versionsSource, url and fetchedAt are always kept — the ones you do not list come first, in that order, and naming one of them here moves it to the position you gave it. An unknown column name is reported in the run's status message instead of being dropped in silence. |
Reference
Coordinate forms
All of these mean the same artifact, and the first three also pin a version:
| What you paste | Read as |
|---|---|
com.google.code.gson:gson:2.10.1 | group com.google.code.gson, artifact gson, pinned 2.10.1 |
"com.google.code.gson:gson:2.10.1" | the same (spaces and quotes are stripped) |
com.squareup.okhttp3:okhttp:4.12.0@aar | group, artifact, pinned 4.12.0 (the Gradle @ext suffix is ignored) |
org.slf4j:slf4j-api | group and artifact, no pin — a release report instead of an upgrade check |
org.example:lib:jar | group and artifact; jar is a packaging, not a version |
A value that cannot be a coordinate at all — a bare artifact name such as gson, an empty part, a group id with a
space — fails the run with a message naming the expected shape. An artifact the index does not know returns a row
with found: false instead of disappearing.
Search qualifiers
The index's own qualifiers, passed on as typed. They may be combined with AND / OR.
| Query | What it finds |
|---|---|
json parser | plain words over artifact names and descriptions |
g:com.squareup.okhttp3 | every artifact a group publishes |
a:okhttp | that artifact id in any group |
c:ObjectMapper | artifacts containing a class with that simple name |
fc:com.fasterxml.jackson.databind.ObjectMapper | artifacts containing that fully qualified class |
tags:kotlin | artifacts the index tagged kotlin |
p:aar | artifacts published as Android archives |
l:sources | artifacts that ship a sources classifier |
A class or version query (c:, fc:, v:) is answered by the index with single versions, so hits are
deduplicated to artifact level: the same artifact found in six versions is one row. On 2026-10-09, the first forty
version answers to c:ObjectMapper covered twelve distinct artifacts — which is why a wide class query can yield
fewer artifacts than searchMaxItems asks for.
Packaging values
Values seen in Central: jar, aar, pom, bundle, war, zip, module. packaging is a free-text field with
these as suggestions, so case, a leading dot and the spellings jars, osgi-bundle and gradle-module are
accepted. Any other value is passed to the filter as typed — Central uses more packagings than the seven above, and
the run status says when a value was used as typed. A value that is a letter or two away from a known packaging
(jarr, pomm) is refused with "did you mean …?" rather than silently matching nothing.
What counts as a prerelease
A version is treated as a prerelease when it carries one of these markers as its own token, in any case:
alpha, beta, rc, cr, milestone or m<N>, snapshot, dev, preview, pre, prerelease, candidate,
ea, incubating, b<N>. So 5.0.0-alpha.16, 3.0.0-beta3, 4.0.0-M3 and 2.0.0.RC1 are prereleases, while
flavour qualifiers are not: 33.4.8-jre, 1.2.3-android and 2.0.0.Final are releases.
When an artifact has published nothing but prereleases (com.squareup.okhttp3:okhttp-java-net-cookiejar has only
5.0.0-alpha.* versions), latestVersion reports the newest of them — there is no release to report instead — and it
is then equal to latestAnyVersion.
What counts as a change for onlyNew
The watch memory keeps the newest version of any kind per artifact (latestAnyVersion with its release date), so a
new prerelease counts as a change and brings the artifact back even with includePrereleases off — the row then
repeats the same latestVersion while latestAnyVersion has moved on (com.squareup.okhttp3:okhttp:
latestVersion 4.12.0, latestAnyVersion 5.0.0-alpha.16). Everything else about an artifact — new tags, a changed
packaging, a version count that grew without a newer version — does not bring it back. The first run writes
everything, and a coordinate Central does not hold repeats only when it starts to exist.
Where a row's versions come from
Every row says it in versionsSource:
| Value | When | What the row holds |
|---|---|---|
history | every coordinate, and search hits with searchHydrate on | the scanned version list: latestVersion derived from the release dates, recentVersions, firstReleasedAt, releasesLast365Days, and the pinned-version answer |
index | search hits with searchHydrate off, and a hit whose history request did not answer | the index entry only: its own latestVersion with the entry's date (a prerelease is possible here), versionCount, packaging. recentVersions, firstReleasedAt and releasesLast365Days stay null |
A search hit is never dropped because the index was slow: it is written from what the search itself returned, and the run status counts those rows.
Examples
Is anything we pinned stale?
{"coordinates": ["com.google.code.gson:gson:2.10.1","org.apache.commons:commons-lang3:3.12.0","org.slf4j:slf4j-api:1.7.36"],"versionsLimit": 5,"maxItems": 10}
Which artifact contains this class?
{ "searchQueries": ["c:ObjectMapper"], "searchMaxItems": 10, "maxItems": 10 }
Which of our dependencies shipped anything this year?
{"coordinates": ["com.google.code.gson:gson","org.apache.logging.log4j:log4j-core","com.google.guava:guava","org.springframework:spring-core","org.apache.commons:commons-lang3"],"releasedSince": "2026-01-01","versionsLimit": 5,"fields": ["latestVersion", "latestVersionReleasedAt", "versionsInWindow", "recentVersions"],"maxItems": 10}
Everything two vendor groups publish, with real release dates
{"searchQueries": ["g:com.squareup.okhttp3", "g:com.squareup.moshi"],"searchHydrate": true,"searchMaxItems": 4,"versionsLimit": 5,"maxItems": 8}
Release cadence of the libraries we depend on
{"coordinates": ["org.jetbrains.kotlin:kotlin-stdlib","org.jetbrains.kotlinx:kotlinx-coroutines-core","com.squareup.okhttp3:okhttp"],"versionsLimit": 25,"maxItems": 10}
Android libraries only, as a daily watch
{"searchQueries": ["tags:android"],"packaging": "aar","searchMaxItems": 50,"onlyNew": true,"maxItems": 50}
Output
One row per artifact. A real row from cloud run 0fWzvkeyRgO4Ebzne (input com.google.code.gson:gson:2.10.1
with versionsLimit: 5; recentVersions trimmed here with …):
{"id": "com.google.code.gson:gson","groupId": "com.google.code.gson","artifactId": "gson","found": true,"versionsSource": "history","latestVersion": "2.14.0","latestVersionReleasedAt": "2026-04-23T19:01:47.000Z","latestVersionAgeDays": 169,"latestAnyVersion": "2.14.0","latestAnyVersionReleasedAt": "2026-04-23T19:01:47.000Z","versionCount": 42,"firstReleasedAt": "2008-08-10T14:29:31.000Z","releasesLast365Days": 1,"packaging": "jar","tags": ["library","json","gson"],"recentVersions": [{"version": "2.14.0","releasedAt": "2026-04-23T19:01:47.000Z","packaging": "jar","prerelease": false},{"version": "2.13.1","releasedAt": "2025-04-24T01:05:20.482Z","packaging": "jar","prerelease": false},{"version": "2.13.0","releasedAt": "2025-04-11T14:30:34.134Z","packaging": "jar","prerelease": false}…],"historyTruncated": false,"versionsInWindow": null,"matchedQuery": null,"pinnedVersion": "2.10.1","pinnedVersionFound": true,"pinnedVersionReleasedAt": "2023-01-06T15:44:01.000Z","pinnedVersionAgeDays": 1372,"isLatest": false,"versionsBehind": 6,"newerVersions": ["2.14.0","2.13.1","2.13.0","2.12.1","2.12.0"],"url": "https://search.maven.org/artifact/com.google.code.gson/gson","fetchedAt": "2026-10-09T21:50:22.957Z"}
| Field | Type | Meaning |
|---|---|---|
id | string | groupId:artifactId — the row key |
groupId, artifactId | string | The coordinate, always filled |
found | boolean | false when the index has no such artifact; the rest of the row is then null |
versionsSource | string | history (versions read and dated) or index (the index entry only) — see Where a row's versions come from |
latestVersion | string | Newest release, derived from the release dates (prereleases excluded unless includePrereleases). With versionsSource: "index" it is instead the index entry's own latest version, which may be a prerelease |
latestVersionReleasedAt | string | Its release date, ISO 8601 UTC; with versionsSource: "index", the date of the index entry |
latestVersionAgeDays | number | Whole days since that release |
latestAnyVersion | string | Newest version of any kind, prereleases included |
latestAnyVersionReleasedAt | string | Its release date |
versionCount | number | Versions the index holds for the artifact (its own total, not only the scanned ones) |
firstReleasedAt | string | Oldest release read; with historyTruncated: true that is the oldest version inside the scanned window. Null with versionsSource: "index" |
releasesLast365Days | number | Versions released in the last 365 days, prereleases included. Null with versionsSource: "index" |
packaging | string | Packaging of the newest release (jar, aar, pom, …) |
tags | string[] | Tags the index keeps for that version; null when it has none |
recentVersions | object[] | Up to versionsLimit recent versions: version, releasedAt, packaging, prerelease. Only versions inside the window when releasedSince is set. Null with versionsSource: "index" |
historyTruncated | boolean | True when maxVersionsScanned stopped the scan before the oldest version |
versionsInWindow | number | Versions released on or after releasedSince; null without that filter |
matchedQuery | string | The search query that produced the row; null for a coordinate |
pinnedVersion | string | The version you pinned; null when you pinned none |
pinnedVersionFound | boolean | False when Central does not have that version |
pinnedVersionReleasedAt | string | Release date of the pinned version |
pinnedVersionAgeDays | number | Whole days since the pinned version was released |
isLatest | boolean | True when nothing newer has been released; false when the pin is unknown to Central; null without a pin |
versionsBehind | number | Releases published after your pin; null without a pin or when the pin is unknown |
newerVersions | string[] | Up to versionsLimit version strings newer than your pin, newest first |
url | string | The artifact's page on the Central search site |
fetchedAt | string | When the row was read, ISO 8601 UTC |
All dates are ISO 8601 in UTC, converted from the index's epoch-millisecond timestamp.
Dataset views: Artifacts (overview), Upgrade check (pinned version, versions behind, newest release),
Release history (dates, counts, recentVersions, versionsSource).
Use it from code / agents
curl -X POST "https://api.apify.com/v2/acts/yadroo~maven-central-artifact-versions/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"coordinates":["com.google.code.gson:gson:2.10.1","org.slf4j:slf4j-api:1.7.36"],"maxItems":10}'
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('yadroo/maven-central-artifact-versions').call({coordinates: ['com.google.code.gson:gson:2.10.1', 'org.slf4j:slf4j-api:1.7.36'],maxItems: 10,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
from apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("yadroo/maven-central-artifact-versions").call(run_input={"coordinates": ["com.google.code.gson:gson:2.10.1", "org.slf4j:slf4j-api:1.7.36"],"maxItems": 10,})items = client.dataset(run["defaultDatasetId"]).list_items().items
MCP: add https://mcp.apify.com to Claude / Cursor / any MCP client and call the
yadroo/maven-central-artifact-versions tool with the same JSON input. coordinates is normally the only field an
agent needs to fill; everything else has a working default.
Pricing
Pay per event: $0.001 per run start + $0.002 per artifact row. Every run is charged the start event, even one
that finds nothing. Every row written to the dataset is charged once — including a found: false marker row, which is
the answer to a coordinate Central does not have, and a search hit written from the index entry. Artifacts dropped by
releasedSince or packaging are not written and not billed.
| Run | Rows | What it costs |
|---|---|---|
| The two prefilled coordinates | 2 | $0.001 + 2 × $0.002 = $0.005 |
| A build file's dependencies | 20 | $0.001 + 20 × $0.002 = $0.041 |
| A typical run of this actor | 50 | $0.001 + 50 × $0.002 = $0.101 |
A keyword search with searchMaxItems 200 | 200 | $0.001 + 200 × $0.002 = $0.401 |
searchMaxItems is the knob that decides what a search query costs: a wide word query with a high value here is the
expensive way to use this actor. Apify's plan discounts apply to the row event (Bronze −10 %, Silver −20 %, Gold and
above −30 %); the start event is the same on every plan. The run also stops at the Maximum cost per run you set on
the platform and keeps every row you already paid for — the status message then says "Stopped at your spending limit:
N rows delivered".
Limits & FAQ
How fast is it? Measured in the Apify cloud on 2026-10-09. One coordinate with up to 200 versions is one
request, and the index normally answers in under a second: three pinned coordinates came back in 15 seconds, fifteen
keyword hits in 1 second, ten class-search artifacts in 30 seconds, eight artifacts of two groups with their full
histories in 116 seconds. A long run is slower, because this index lets single requests stall for half a minute and
the actor then slows itself down: 50 coordinates took 361 seconds — 49 rows and 79 requests, about 8 artifacts and
13 requests per minute (run PsbL05k4q8lUINhnU; 14 of those 79 requests stalled and were retried, none of the 49
lookups was lost). Plan on seconds for a handful of coordinates and on six to seven minutes for a build file's worth
of them.
What fits into the run timeout? The 900-second default timeout is sized for the slow case, not the fast one: the
50 coordinates the input allows took 361 seconds in the measurement above, and a stalling index can halve what a
short run returns — the same input with a 60-second timeout saved 6 rows (run eissMVtfBF7SPnFJq). The default does
not cover every extreme the schema permits: 50 coordinates plus ten search queries of 200 hydrated hits each is
thousands of requests. Such a run stops early, keeps every row it has read and says so: "Stopped before the run
timeout: N rows saved". Split the work, or raise the timeout in the run options.
Rate limit. Sonatype's REST API guide documents no rate limit for the search endpoint and robots.txt sets no
Crawl-delay, so this actor applies the house default: one request per second per host with a burst of three, for
every request including retries. There are no 429 answers; what the index does instead is let a request stall for
half a minute or more. Such a request is cut after 12 seconds and tried again — measured on 2026-10-09, the same URL
that stalled answered in 0.3 seconds on the next attempt — with four attempts in all, the last two waiting the full
30 seconds, and the actor halves its own pace after every stall, down to one request every four seconds. Asking
less often is what gets a long run through. An artifact whose history still could not be read is reported in the run
status instead of failing the run, and a search hit is then written from its index entry.
A run stops before its timeout. When the run would otherwise be killed by the Apify timeout, it stops starting new work, keeps every row already read and ends successfully with "Stopped before the run timeout: N rows saved" in the status message. The same happens at your maximum cost per run. Raise the timeout, raise the cost cap, or split the coordinate list.
One request per 200 versions. A history is read in pages of 200 versions, newest first, and never deeper than
maxVersionsScanned (default 400). Almost every library fits in one request; an SDK that publishes daily does not —
then historyTruncated is true, versionCount still shows the index's own total, and firstReleasedAt is the
oldest version inside the scanned window. Raise maxVersionsScanned to read deeper, at one more request per 200
versions.
Newest by date is not always the highest number. latestVersion, versionsBehind and newerVersions follow
release dates, as the field table says. Libraries that maintain several lines in parallel publish a patch of an older
line after a newer minor: a 2.18.x patch released after 2.19.0 becomes the newest release by date, so a pin of
2.19.0 can show isLatest: false with versionsBehind: 1. recentVersions shows the lines side by side with their
dates, so you can see which release you actually want.
Central only. The rows are what the Maven Central search index holds. Artifacts published only to Google's
Android repository (the androidx.* groups), to JitPack or to a company Nexus are not in this index and come back as
found: false. SNAPSHOT versions are not published to Central at all.
No deprecation or breaking-change data. Central publishes versions, dates and packaging — nothing about API compatibility, deprecations or whether an upgrade will break your build. This actor answers "what exists, when was it released, how far behind am I"; it cannot answer "is it safe to upgrade", because no field for that exists in this source.
Why not use the index's own "latest version"? Because it is often wrong for an upgrade check: on 2026-10-09 the
index entry for org.apache.logging.log4j:log4j-core named 3.0.0-beta3 from 2024 while the artifact's newest
release in the same index was 2.26.0 from 2026-05. A row with versionsSource: "history" derives the newest release
from the release dates and keeps prereleases in a separate field; a row with versionsSource: "index" reports the
entry's value as it is.
Freshness and gaps. The index is kept by Central itself and is usually current shortly after a release, but
coverage is uneven for some artifacts — com.google.guava:guava holds 150 versions whose newest is from 2025-04.
Treat the rows as what the index holds, not as a guarantee about the repository, and never as real time.
Empty results. A coordinate the index does not know gives a found: false row. A search query with no match
gives no row and says so in the run status. An input that cannot be a coordinate fails the run with a message naming
the expected shape — never a silent empty success.
Questions or problems: open an issue on the Issues tab of this actor.
Made by Yadroo. Sibling actors: npm-package-intel, pypi-package-intel, github-repo-intel, cisa-kev-vulnerabilities, domain-intel.
