GitHub Releases Monitor & Scraper avatar

GitHub Releases Monitor & Scraper

Pricing

from $2.70 / 1,000 published release saveds

Go to Apify Store
GitHub Releases Monitor & Scraper

GitHub Releases Monitor & Scraper

Read public GitHub release notes and asset metadata. Compare a previous snapshot to find new or changed releases. Start without a token and export JSON or CSV.

Pricing

from $2.70 / 1,000 published release saveds

Rating

0.0

(0)

Developer

Cliqto Media

Cliqto Media

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Categories

Share

Read published releases from known public GitHub repositories. Get release notes in Markdown, dates, stable release IDs and asset metadata. Compare your own previous snapshot to find new or changed releases.

Start with the small example in the Input form. No GitHub token is needed. The price is $0.05 per start plus $0.0027 per saved release. A source limit, rate limit or filter can make the result partial or empty. Check RUN_SUMMARY before using an empty result.

GitHub Releases Monitor and Scraper: release notes, asset metadata, and snapshot comparison

Table of contents

What it does

Add up to 10 public repositories. Choose list for a bounded window of releases in GitHub source order. Choose latest for GitHub's selected stable release. Read the results as JSON or export CSV.

Use this Actor to watch software you depend on, collect release notes, or check asset names and download counts. It reads the GitHub Releases REST API. A tag without a published Release is not a result.

Data you get

Each Dataset row is one published release. It has the repository, immutable GitHub release ID, tag, nullable name and notes, dates, prerelease flag, release URL and author. Assets have IDs, names, sizes, content types, download counts and download URLs. The Actor reads metadata and does not download asset files.

Notes stay in Markdown. Notes may contain HTML text; the Actor does not render it. Notes are kept up to 20,000 UTF-16 code units and assets up to 100 per release. Flags show when these fields were cut.

Quick start

  1. Open Input in Apify Console.
  2. Keep the form example: repositories is ["cli/cli"], mode is list, and both release limits are 2.
  3. Leave githubToken empty and onlyChanges off.
  4. Click Start. Use the default build and 256 MB memory.
  5. Open the Dataset. Check repository, releaseId, tagName and assets. Open RUN_SUMMARY to check coverage.

The example reads two releases each time. It reports partial because two releases are a small window, not the full repository history. The required repositories field has a UI prefill, not an API runtime default. API input {} fails validation; it does not run the demo for you.

Input reference

FieldType / requiredRuntime default / UI prefillAllowed valuesEffect and recommendation
repositoriesstring array; requiredno default; prefill ["cli/cli"]1–10 input stringsPublic owner/name or exact https://github.com/owner/name, with an optional final slash. Start with one repo. Case and duplicate values share one scan.
modestringlist / listlist, latestList a window or get the GitHub latest stable release. Latest is not a semantic-version sort.
includePrereleasesbooleantrue / truetrue, falseFilter prereleases in list mode. Latest always excludes them.
maxReleasesPerRepositoryinteger10 / 21–500Maximum raw releases examined per repo, before filtering. Skipped prereleases use this window. Latest examines at most one release.
maxResultsinteger100 / 21–1,000Maximum saved Dataset rows across the run. Small output does not always mean a small source scan.
onlyChangesbooleanfalse / falsetrue, falseRequires previousSnapshot. Saves only added and changed rows. Leave off for a repeatable demo.
previousSnapshotobjectabsent / noneSnapshot v1, at most 1,000 entriesPaste your previous SNAPSHOT record. Mode, prerelease setting and per-repo window must match. Use the full record.
githubTokensecret stringabsent / noneExisting token; letters, digits and underscore, up to 255 charactersOptional for public API requests. Apify encrypts this input. Do not put tokens in other fields. Private repositories stay blocked.
maxRequestsinteger20 / none1–30Total attempts, including retries, redirects and public checks. Keep the default for a small scan.
requestTimeoutSecsinteger20 / none5–30 secondsTimeout per request, within the scan deadline.
deadlineSecsinteger120 / none10–180 secondsDeadline for scan work and retries. Keep the Cloud run timeout at 240–300 seconds so output can finish saving.

Moved repository aliases can return a canonical GitHub URL with a new owner. The repository, owner, repositoryName and stable id keep your normalized input scope. Use one canonical name per repository; two different aliases are separate inputs.

Empty arrays, null settings, unknown fields, bad types and arbitrary URLs fail validation before source requests. URLs with credentials, query strings, fragments, encoded path parts or extra paths are not accepted. Omit an optional field to use its default; do not send null. A snapshot with a different scope fails validation.

Snapshot input fields

previousSnapshot uses the same fields as the SNAPSHOT output below. contractVersion, scope, repositories and entries are required. Every nested field listed there is required, including nullable coverage fields. Copy the whole record rather than making a new one by hand. Do not add credentials or release bodies to the snapshot.

Settings that work together

SettingsResult
mode=latest + includePrereleases=trueGitHub latest still selects a stable release.
includePrereleases=false + small source windowThe Dataset can be empty even when the repo has stable releases further back. Increase the window within the limits.
onlyChanges=true + unchanged snapshotEmpty Dataset; the new snapshot and coverage are still saved. Start price still applies.
maxResults or snapshot limit reachedLater work stops. A partial snapshot cannot prove deletion.
Optional tokenAn anonymous public-repository check happens first. It adds one request per repo. A token never gives access to private repos through this Actor.

Input examples

Two releases with notes and assets

{
"repositories": ["cli/cli"],
"mode": "list",
"includePrereleases": true,
"maxReleasesPerRepository": 2,
"maxResults": 2,
"onlyChanges": false
}

Expect two release rows, with releaseId, tagName, body and assets. The list is a partial source window.

GitHub latest stable release

{
"repositories": ["react/react"],
"mode": "latest"
}

Expect the release selected by GitHub's latest endpoint. A repo with no stable release returns zero rows and complete; a missing or inaccessible repo returns not_found.

Compare a previous scan

First run the list example and copy its SNAPSHOT record. Run the same example again with that object in previousSnapshot. Leave onlyChanges=false to keep the current release rows and see their change value. Use onlyChanges=true to keep only new or changed rows.

Output example

{
"id": "cli/cli:399674740",
"repository": "cli/cli",
"owner": "cli",
"repositoryName": "cli",
"repositoryUrl": "https://github.com/cli/cli",
"releaseId": 399674740,
"tagName": "v2.102.0",
"name": "GitHub CLI 2.102.0",
"body": "## Security\n\nFour security vulnerabilities have been identified, and fixed, in this release. Users are advised to update gh to version `v2.102.0` as soon as possible.\n\n`gh release download`, `gh run download`, `gh repo read-file --output`, and `gh attestation download` could write remote content to an unintended local file when the destination contained symbolic links.\n\nSee https://github.com/cli/cli/security/advisories/GHSA-39wj-f2f4-978v for mo",
"notesFormat": "markdown",
"createdAt": "2026-09-30T02:18:02Z",
"publishedAt": "2026-09-30T02:40:02Z",
"prerelease": false,
"releaseUrl": "https://github.com/cli/cli/releases/tag/v2.102.0",
"author": {
"login": "github-actions[bot]",
"url": "https://github.com/apps/github-actions"
},
"assets": [
{
"id": 599854636,
"name": "gh_2.102.0_checksums.txt",
"contentType": "text/plain; charset=utf-8",
"size": 1971,
"downloadCount": 54188,
"downloadUrl": "https://github.com/cli/cli/releases/download/v2.102.0/gh_2.102.0_checksums.txt"
}
],
"notesTruncated": false,
"assetsTruncated": false,
"retrievedAt": "2026-10-07T01:30:15.660Z",
"change": "initial"
}

This is a real row from the two-release example. For display, the notes are shown as a short excerpt and only the first asset is shown. The two truncation flags describe the actual run, not this shortened example. Download counts and current release tags can change.

Output reference

All release fields below are present in every Dataset row. Nullable values come from the API; empty text is kept as empty text.

FieldType / nullExampleMeaning
idstringcli/cli:399674740Repository plus immutable release ID; use this to join scans.
repositorystringcli/cliNormalized input owner/name, lower case.
ownerstringcliRepository owner.
repositoryNamestringcliRepository name without the owner.
repositoryUrlstringhttps://github.com/cli/cliCanonical public repository URL. A moved repository can have a different owner.
releaseIdinteger399674740Immutable GitHub database ID, not the tag.
tagNamestringv2.102.0Release tag as given by GitHub.
namestring or nullGitHub CLI 2.102.0API release name. Empty and null are different.
bodystring or null## SecurityRelease notes in Markdown, up to 20,000 code units.
notesFormatstringmarkdownNotes format; does not mean rendered HTML.
createdAtISO string or null2026-09-30T02:34:29ZAPI creation time. It can refer to the release's commit time.
publishedAtISO string or null2026-09-30T02:40:02ZAPI publication time.
prereleasebooleanfalseWhether GitHub marks the release as a prerelease.
releaseUrlstringURL in the example aboveCanonical GitHub release page.
authorobject or null{"login":"cli","url":"https://github.com/cli"}API author, when available. login and url are strings.
assetsarray; empty allowedSee the exampleUp to 100 asset records from the API; no binary download.
notesTruncatedbooleanfalseNotes exceeded the retained limit.
assetsTruncatedbooleanfalseThe returned API asset array exceeded 100.
retrievedAtISO string2026-10-07T01:30:15.000ZTime this release was read.
changestringinitialinitial without a baseline; otherwise added, changed or unchanged.

Asset fields

Each asset has all six fields: id (integer, API asset ID), name (string, file name), contentType (string or null, MIME type), size (integer bytes), downloadCount (integer downloads at fetch time) and downloadUrl (string, public GitHub download URL). For example, size: 20747036 is metadata; these bytes were not downloaded by this Actor.

Dataset and Key-value store

SurfaceContents
Default DatasetSaved release rows only. Domain-empty and error results do not add fake release rows.
OUTPUTreleases, repositories, snapshot, diff, summary. Releases match the Dataset; the other fields match the records below.
SNAPSHOTFingerprints and coverage for your next scan. No token or notes body.
RUN_SUMMARYStatus, source scope, counters and reasons. Read it for empty or partial results.

SNAPSHOT.contractVersion is integer 1. scope has mode (list/latest), includePrereleases (boolean), maxReleasesPerRepository (integer; one in latest mode), notesChars (integer 20000) and assetsLimit (integer 100).

SNAPSHOT.repositories is an array of coverage objects. Each has repository (string), status (string), fullHistory (boolean), reason (string or null), examined, emitted, attempts (integers), remaining (integer or null, last API quota header) and resetAt (ISO string or null, last API reset header). Status is complete, partial, not_found, rate_limited or error. fullHistory is true only for a complete list scan with no next page. Latest is always a selected view, not full history.

SNAPSHOT.entries is an array of objects with id, repository, fingerprint (strings) and releaseId (integer). Fingerprints cover retained release fields. They exclude retrieval time and asset download counts. Changes beyond a truncated notes or assets window may not be detected.

OUTPUT.diff has added, changed, removed (arrays of stable ID strings) and removalCheckedRepositories (array of repo names). Removal is checked only when both scans cover a full list history with the same scope. A truncated list, latest scan, failed request or rate limit never proves removal. Added and changed arrays cover the successfully processed snapshot entries.

RUN_SUMMARY has contractVersion (integer), status (complete, partial, error, invalid_input), reason (string or null), sourceCommit (string), startedAt, finishedAt (ISO strings), repositoryCount, releaseCount, examined, requests, retries, bytes, chargedRows (integers), stopped, authenticated (booleans), and repositories (the coverage array above). bytes counts API response body bytes read; requests includes retries and redirects. chargedRows counts acknowledged saved rows; the platform billing record is the source for actual charges.

Price and cost examples

The price is $0.05 per Actor start + $0.0027 per saved release ($2.70 per 1,000 release rows). Platform usage during a standard run is included. There are no proxy, token or asset-download events.

Start price applies to zero releases, a filter with no matches, and unchanged monitoring. Only Dataset release rows incur the release event. Duplicates in the input share one scan. Partial runs pay for the start and rows already saved. A failed or cancelled run may still have a start charge and saved rows. A storage acknowledgement failure is not replayed; a saved row and its charge cannot be made atomic across services.

Saved releases in one standard runStartRelease chargeTotal
0$0.05$0.00$0.05
1$0.05$0.0027$0.0527
10$0.05$0.027$0.077
100$0.05$0.27$0.32
1,000$0.05$2.70$2.75

These are event price calculations, not a promise of a fixed number of releases. Post-run storage reads, exports and retained storage may have standard Apify charges. Set a maximum total charge in Console or the API. If less than one more release fits, the Actor stops with charge_limit. A complete scan can still cost a start when no rows match.

Use cases

JobInputUseful output
Watch dependenciesYour known repositories; list or latesttagName, publishedAt, body, releaseUrl
Check an asset catalogueA CLI or desktop application's repoAsset name, content type, size and download URL
Build a release-note reportSmall list windows across several reposMarkdown notes, stable IDs and dates
Track release editsMatching previousSnapshotchange, diff IDs and the current snapshot

Monitoring and schedules

You control the baseline. Save your run's SNAPSHOT and pass it to the next run. The Actor does not read a global state or another user's scan. If you keep onlyChanges=false, a repeat scan returns the current window even when nothing changed.

You may create an Apify schedule yourself for a list or latest snapshot. A schedule with changing baselines needs your own process to pass the previous SNAPSHOT. This Actor does not create a schedule or webhook and does not update a saved task for you.

API, export and integrations

Start runs from Apify Console or the Actor API. Send JSON with repositories and the settings above. Use maxTotalChargeUsd as an API run option; it is not an Actor input field. Set memory to 256 MB and timeout to 240–300 seconds.

Read the default Dataset for releases, and the default Key-value store for OUTPUT, RUN_SUMMARY and SNAPSHOT. Dataset export supports JSON and CSV. In the Apify run API, the completed run gives you defaultDatasetId, defaultKeyValueStoreId and buildId. Use stable id values to join your records.

A downstream integration can start the run and read these storage records. This Actor does not include a custom MCP server or send messages to third-party services.

Limits and partial results

  • Up to 10 repository inputs, 500 raw releases per repository, 1,000 saved rows and 1,000 snapshot entries per run. A successful Cloud scan returned 1,000 real releases; smaller repositories can return fewer.
  • Hard process deadline of 300 seconds; sequential requests; up to 30 attempts, two retries per request, 8 MiB per response and 32 MiB response bodies per run. No IP or proxy rotation to bypass GitHub quota.
  • Anonymous GitHub REST requests are limited to 60 per hour per IP. Shared Cloud egress can use this quota before your run. Existing authenticated tokens often have higher limits, but secondary limits still apply. See GitHub rate limits.
  • Source order is kept. No promise of all history, highest semantic version, every asset beyond the returned API array, or a consistent database snapshot while GitHub changes between pages.
  • No private repositories, drafts, bare tags, issues, commit scraping, binary downloads, source mutations or repository search.
  • A partial scan keeps useful saved rows. Reasons include repository_limit, result_limit, snapshot_limit, request_limit, byte_limit, deadline, cancelled and charge_limit. Check each repository outcome.
  • No proxy is used. Rate-limit headers and Retry-After are respected. If the reset is outside the deadline, the run reports the rate limit instead of waiting for an hour.

Troubleshooting

Use 256 MB memory. An unsupported resource setting fails with RUN_SUMMARY.status=error and reason=resource_error, before source requests. A longer Cloud timeout does not increase the source deadline or the 300-second process limit.

Empty Dataset: Check RUN_SUMMARY. A valid repo can have no releases, no stable latest release, no matching prereleases or no changes. A short window with includePrereleases=false may skip every entry. These cases differ from not_found and rate_limited.

rate_limited: Wait until the reported resetAt, reduce the scan or use an existing allowed token. Do not keep retrying against the same quota.

invalid_input: Check the required array, exact repo syntax, types and limits. For a snapshot, use the whole record with matching scope. API {} has no demo default.

Missing fields or truncated notes: Null comes from the API. Check notesTruncated and assetsTruncated. The retained window is also the comparison window.

Run failed: Read the safe reason in RUN_SUMMARY. An all-source failure ends the run as FAILED; it is not a successful empty scan. A storage failure can prevent the final records from being written. Keep the run ID for support.

FAQ

Do I need a GitHub token?

No for the small demo. The optional githubToken field is encrypted using Apify secret input. Never paste it into repository URLs, notes or support messages. The authenticated path is covered by fixture tests; a live authenticated run has not been observed for this release.

Can I scrape private repositories with my token?

No. The Actor first checks that the repository is anonymously accessible. A 404 cannot distinguish a missing repository from a private one.

Does latest include prereleases or find the highest version?

No. It uses GitHub's stable latest endpoint. List mode can include prereleases. The Actor does not sort semantic versions.

Does an unchanged run return zero rows?

Only if you pass a matching previousSnapshot and set onlyChanges=true. With the default onlyChanges=false, you still get current release rows with change=unchanged.

Does a missing release mean it was removed?

Only when both scans have a complete and comparable full list history. Bounded windows and latest mode do not prove deletion. The baseline must be your real previous snapshot.

Do download counts trigger a changed release?

No. Counts are returned as current metadata but excluded from the fingerprint. Notes, names, dates and retained asset metadata can trigger a change.

RSS & Atom Feed Reader and Monitor reads feeds when your source publishes news or updates outside GitHub Releases.

Support

Use the Actor's Issues tab in Apify Console for bugs or questions. Include the run ID, mode, public repository names and safe summary reason. Never include tokens, cookies or private account data.