OCaml Packages Scraper
Pricing
from $7.00 / 1,000 results
OCaml Packages Scraper
Scrape public OCaml.org package pages and return structured records for package versions, including synopses, descriptions, licenses, authors, maintainers, dependencies, checksums and publish dates. Search by free text or author filter, or provide package names and version URLs.
Pricing
from $7.00 / 1,000 results
Rating
0.0
(0)
Developer
Axiom Works
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Returns: one row per OCaml package version with name, version, synopsis, license, authors, dependencies, checksums, publishedAt.
Input: {"searchQueries": ["yaml"], "maxItems": 50}
Best for: dependency audits of OCaml projects, license and supply-chain checks, tracking new releases of opam packages.
{"name": "lwt","version": "6.1.2","isLatest": true,"synopsis": "Promises and event-driven I/O","license": "MIT","publishedAt": "2026-04-29","installCommand": "opam install lwt","usedByCount": 511}
What does OCaml Packages Scraper do?
OCaml Packages Scraper turns the package pages of ocaml.org into clean JSON. ocaml.org has no public per-package JSON API, so this Actor works as an OCaml package API: give it search queries (the same ones you would type into the ocaml.org package search, including filters such as author:"Jérôme Vouillon") or a list of opam package names and URLs, and it returns one structured record per package version.
Each record holds the package name and version, whether that version is the latest, the one-line synopsis and the longer description, the license, homepage, opam file link and number of published versions, the authors and maintainers, the source archive URL with its checksums, the date the version was added to opam-repository, the install command, and the full dependency lists (runtime and development) with their version constraints. It also counts how many packages depend on this one.
The Actor reads public pages only. No login, no account and no API key for ocaml.org are needed. It is useful for dependency audits, license reviews, software bills of materials, release monitoring, and building datasets of the OCaml ecosystem.
What data can you get from ocaml.org?
| Field | Description | Example |
|---|---|---|
id | Stable record ID: name@version | lwt@6.1.2 |
name | opam package name | lwt |
version | Package version | 6.1.2 |
isLatest | True when this is the newest version | true |
synopsis | One-line summary of the package | Promises and event-driven I/O |
description | Longer description, paragraphs separated by a blank line; null when there is none | A promise is a value that may become determined in the future. |
license | License from the license link, without the word "License", or the first sentence of the README License paragraph; null when both are absent | MIT |
homepage | Project homepage or repository | https://github.com/ocsigen/lwt |
opamFileUrl | The opam file in opam-repository | https://github.com/ocaml/opam-repository/blob/master/packages/lwt/lwt.6.1.2/opam |
versionsCount | Number of published versions | 32 |
authors | Author names | ["Jérôme Vouillon", "Jérémie Dimino"] |
maintainers | Maintainer names, sometimes with an email | ["Raphaël Proust <code@bnwr.net>", "Anton Bachin"] |
sourceArchiveUrl | Download URL of the release source archive | https://github.com/ocsigen/lwt/archive/refs/tags/6.1.2.tar.gz |
checksums | Archive checksums as algorithm=hex | ["md5=00bc7eb2772a28530f7365a7040f0c4f", "sha512=a473..."] |
publishedAt | Date added to opam-repository (YYYY-MM-DD) | 2026-04-29 |
installCommand | opam command that installs this version | opam install lwt |
dependencies | Dependencies as {name, constraint} objects | [{"name": "dune", "constraint": ">= \"3.18\""}] |
devDependencies | Test, doc and dev dependencies as {name, constraint}; empty when none | [{"name": "odoc", "constraint": "with-doc & >= \"2.3\""}] |
dependenciesCount | Number of dependencies | 5 |
usedByCount | Number of packages that depend on this one; 0 when none | 511 |
docsUrl | Package documentation on ocaml.org | https://ocaml.org/p/lwt/latest/doc/index.html |
packageUrl | The package page that was scraped | https://ocaml.org/p/lwt/latest |
searchQuery | The search query that found the package; null for packages input | http |
scrapedAt | Time of the scrape (ISO 8601, UTC) | 2026-10-15T19:08:56.393Z |
sourceUrl | Page the record came from | https://ocaml.org/p/lwt/latest |
How to use OCaml Packages Scraper
- Open OCaml Packages Scraper in Apify Console and go to the Input tab.
- Type one or more search queries (for example
yaml,httporauthor:"Jérôme Vouillon"), or list packages by name or URL (for examplelwt,yojson@2.1.0orhttps://ocaml.org/p/yojson/2.1.0). You can use both fields in the same run. - Set Maximum results to the number of packages you want in total.
- Click Start. Each search query is paged through the ocaml.org package search, 50 results per page, and every result's package page is opened and parsed.
- When the run finishes, open the Output tab, or export the dataset as JSON, CSV, Excel, XML or RSS.
Tips:
A bare package name always gives the latest version. To get an older release, use name@version, name.version or a full version URL such as https://ocaml.org/p/yojson/2.1.0; that record then has isLatest set to false.
maxItems is one budget shared by every target in the run. Packages listed under packages are scraped first, then the search queries in order, so a large first search can use the whole budget. If the same package version turns up twice (in two searches, or as a package and a search result), it is returned once.
The Actor keeps a modest pace (about two requests per second) so a run of 50 packages usually finishes in well under a minute.
Input
| Field | Type | Required | Description |
|---|---|---|---|
searchQueries | array of strings | One of the two | ocaml.org package search terms, free text or filters such as author:"Name". Every result's package page is scraped. Use * to walk the whole package index (set maxItems to bound it). |
packages | array of strings | One of the two | opam package names (lwt), name@version (yojson@2.1.0) or ocaml.org package URLs (https://ocaml.org/p/yojson/2.1.0). |
maxItems | integer | No | Maximum number of packages across all targets, 1-10000, default 50. |
proxyConfiguration | object | No | Proxy settings. Default: no proxy (ocaml.org works without one). |
Give at least one search query or one package. A search URL copied from ocaml.org (https://ocaml.org/packages/search?q=yaml) also works in either field.
{"searchQueries": ["yaml", "author:\"Jérôme Vouillon\""],"packages": ["lwt", "https://ocaml.org/p/yojson/2.1.0"],"maxItems": 50,"proxyConfiguration": { "useApifyProxy": false }}
Output
Each package version is one item in the run's dataset. These two items come from a real run with {"packages": ["lwt", "https://ocaml.org/p/yojson/2.1.0"]} (the lwt description is shortened here):
[{"id": "lwt@6.1.2","name": "lwt","version": "6.1.2","isLatest": true,"synopsis": "Promises and event-driven I/O","description": "A promise is a value that may become determined in the future.\n\nLwt provides typed, composable promises. ...","license": "MIT","homepage": "https://github.com/ocsigen/lwt","opamFileUrl": "https://github.com/ocaml/opam-repository/blob/master/packages/lwt/lwt.6.1.2/opam","versionsCount": 32,"authors": ["Jérôme Vouillon", "Jérémie Dimino"],"maintainers": ["Raphaël Proust <code@bnwr.net>", "Anton Bachin"],"sourceArchiveUrl": "https://github.com/ocsigen/lwt/archive/refs/tags/6.1.2.tar.gz","checksums": ["md5=00bc7eb2772a28530f7365a7040f0c4f","sha512=a4737a2fc44aaeedca46ec6134c07013d5cf44039a988a6e79a40715a53e43601d4c91bbf11a8e89540528d912b8fa487e3068465c136c1156a872258eb3443b"],"publishedAt": "2026-04-29","installCommand": "opam install lwt","dependencies": [{ "name": "ocplib-endian", "constraint": null },{ "name": "dune-configurator", "constraint": null },{ "name": "cppo", "constraint": "build & >= \"1.1\"" },{ "name": "ocaml", "constraint": ">= \"4.14\"" },{ "name": "dune", "constraint": ">= \"3.18\"" }],"devDependencies": [{ "name": "odoc", "constraint": "with-doc & >= \"2.3\"" },{ "name": "ocamlfind", "constraint": "dev & >= \"1.7.3-1\"" }],"dependenciesCount": 5,"usedByCount": 511,"docsUrl": "https://ocaml.org/p/lwt/latest/doc/index.html","packageUrl": "https://ocaml.org/p/lwt/latest","searchQuery": null,"scrapedAt": "2026-10-15T19:08:56.393Z","sourceUrl": "https://ocaml.org/p/lwt/latest"},{"id": "yojson@2.1.0","name": "yojson","version": "2.1.0","isLatest": false,"synopsis": "Yojson is an optimized parsing and printing library for the JSON format","description": "Yojson is an optimized parsing and printing library for the JSON format.\n\nydump is a pretty-printing command-line program provided with the\nyojson package.","license": "BSD-3-Clause","homepage": "https://github.com/ocaml-community/yojson","opamFileUrl": "https://github.com/ocaml/opam-repository/blob/master/packages/yojson/yojson.2.1.0/opam","versionsCount": 15,"authors": ["Martin Jambon"],"maintainers": ["paul-elliot@tarides.com", "nathan@tarides.com", "marek@tarides.com"],"sourceArchiveUrl": "https://github.com/ocaml-community/yojson/releases/download/2.1.0/yojson-2.1.0.tbz","checksums": ["sha256=9fcb1ff2db58ab259f9228796b0ada4794eae97177b1833371380c4e4f90b15d","sha512=31ab8580e0e4e8a05459fbec2fb9424a3df4cf5aef6df21fc577dbe3d32e81103a632c6a511c4dcf1f51819e88b38d2ce7d6888545bc3f359e69e070f8d2e69c"],"publishedAt": "2023-05-02","installCommand": "opam install yojson.2.1.0","dependencies": [{ "name": "seq", "constraint": ">= \"0.2.2\"" },{ "name": "cppo", "constraint": "build" },{ "name": "ocaml", "constraint": ">= \"4.02.3\"" },{ "name": "dune", "constraint": ">= \"2.7\"" }],"devDependencies": [{ "name": "odoc", "constraint": "with-doc" },{ "name": "alcotest", "constraint": "with-test & >= \"0.8.5\"" }],"dependenciesCount": 4,"usedByCount": 287,"docsUrl": "https://ocaml.org/p/yojson/2.1.0/doc/index.html","packageUrl": "https://ocaml.org/p/yojson/2.1.0","searchQuery": null,"scrapedAt": "2026-10-15T19:08:56.963Z","sourceUrl": "https://ocaml.org/p/yojson/2.1.0"}]
Fields that a package page doesn't show are null (single values) or an empty list (lists), so every item has the same shape. For example, some packages have neither a license link nor a README License paragraph, or have no description.
How much does it cost to scrape ocaml.org?
OCaml Packages Scraper is charged per result. You pay only for the package records returned, and maxItems caps how many that can be. Searches that match nothing, unknown packages and failed pages cost nothing. See the Pricing tab for the current price.
Use with AI agents (MCP)
Connect OCaml Packages Scraper to Claude, Cursor or any MCP client through the Apify MCP server:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com/?tools=axiomworks/ocaml-packages-scraper"}}}
Example prompts:
- "Use the OCaml packages scraper to get lwt, cmdliner and yojson, and list each one's license, latest version and dependencies with constraints."
- "Search ocaml.org for packages by author:"Jérôme Vouillon" and make a table of name, version, publish date and how many packages use each one."
- "Find the 20 most relevant OCaml HTTP packages and tell me which have no license value or have not had a release since 2024."
An agent sees the input fields searchQueries, packages and maxItems, so it can search or look up exact packages in one call.
Integrations and API
Run OCaml Packages Scraper from your own code with the Apify API. Set APIFY_TOKEN to your Apify API token (send it in the Authorization header, never in the URL).
Python
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("axiomworks/ocaml-packages-scraper").call(run_input={"packages": ["lwt", "yojson@2.1.0"], "searchQueries": ["yaml"], "maxItems": 50})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["id"], item["license"], len(item["dependencies"]))
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('axiomworks/ocaml-packages-scraper').call({searchQueries: ['yaml'],maxItems: 50,});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const p of items) {// p.name, p.version, p.isLatest, p.dependencies ...}
cURL
curl -X POST "https://api.apify.com/v2/acts/axiomworks~ocaml-packages-scraper/run-sync-get-dataset-items" \-H "Authorization: Bearer $APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"searchQueries": ["yaml"], "maxItems": 20}'
The Integrations tab connects the Actor to Make, Zapier, n8n, Google Sheets, Slack and webhooks, so you can, for example, send a row to a spreadsheet for every package version in a weekly scheduled run.
FAQ
Is there an official ocaml.org JSON API for packages? Not for package metadata. The package pages are HTML, so this Actor reads them and returns the same data as structured JSON. Think of it as an OCaml package API you can call from code or from an AI agent.
How do I get an older version of a package?
Use name@version (for example yojson@2.1.0) or the version's URL (https://ocaml.org/p/yojson/2.1.0) in packages. A bare name and every search result give the latest version.
Which search queries work?
Anything the ocaml.org package search accepts: free text such as json or http server, and filters such as author:"Anil Madhavapeddy". Non-ASCII names work as typed.
Why did my run return 0 results? The search matched no packages, or the package name doesn't exist on ocaml.org (HTTP 404). The run still ends as succeeded, and the log and status message say which target found nothing. Check the spelling, or try the search on ocaml.org first.
Why is license or description null for some packages?
License uses the sidebar license link first, then the first sentence or short text of the paragraph immediately after the README License heading. Some package pages have neither source, or no description section. The Actor returns null instead of guessing. The opam file (opamFileUrl) is the place to check those packages by hand.
How fresh is the data?
Every run reads the live pages, so the data is as current as ocaml.org at the time of the run (scrapedAt). Schedule the Actor to track new releases.
Do I need a proxy? Usually not. ocaml.org answers normal requests without one, so the default is no proxy. If you see HTTP 403 or 429 in the log, turn on Apify Proxy; blocked requests are retried on a new session automatically.
How many packages can one run return?
Up to 10,000 (maxItems). Large searches are paged 50 results at a time until the search runs out or maxItems is reached.
Is it legal to scrape ocaml.org?
This Actor collects only publicly available package metadata that anyone can see on ocaml.org without logging in. Package pages list author and maintainer names and sometimes email addresses; if you store or process those, you are responsible for doing so lawfully (for example under GDPR) and for respecting the site's terms. This is not legal advice.
OCaml Packages Scraper is an independent tool. It is not affiliated with, endorsed by or sponsored by ocaml.org or the OCaml Software Foundation.
Feedback
Found a bug or need a field that isn't here? Open an issue on the Issues tab and we'll look at it.