Met Museum Scraper: Artworks by Keyword
Pricing
Pay per usage
Go to Apify Store

Met Museum Scraper: Artworks by Keyword
Search the Metropolitan Museum of Art collection by keyword via its public API: artist, date, medium, department and image. No login, no proxy, no browser.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Naimur Hasan
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Met Museum Scraper
Searches the Metropolitan Museum of Art's collection by keyword through its public Collection API. No login, no proxy, no browser.
Input
| Field | Type | Notes |
|---|---|---|
query | string | Required. Free-text search, e.g. sunflowers. Default sunflowers. |
maxItems | integer | Cap on artworks returned. Default 10. |
hasImages | boolean | Restrict to objects that have an image. Default true. |
Output
One row per artwork: objectId, title, artist, artistNationality,
objectDate, medium, dimensions, department, classification,
culture, isPublicDomain, primaryImage, creditLine,
accessionNumber, objectUrl.
Notes
- Search lives on v1.1; object detail still lives on v1. The Met retired
the Solr-backed
/v1/searchon 2026-10-01 — it answers HTTP 410 with a pointer to the Elastic-backed/v1.1/search, which is paginated byoffsetandlimitand caps a page at 500. There is no/v1.1/objects, so the two halves of a run deliberately use different API versions. - An empty page comes back as
objectIDs: null, not[]. Both a query that matches nothing and an offset past the end return null, so the result is normalised before anything iterates it. - The Met splits this into two endpoints: search returns only object IDs, and
each object costs its own request.
maxItemsis therefore the main lever on how long a run takes. - The object endpoint is behind a WAF that rate limits bursts. Firing
requests back to back returned HTTP 403 with an HTML challenge page for 39
of 100 objects, and the block then applied to every request from that IP for
about 30 seconds. Requests are now spaced 250 ms apart and retried with a
capped backoff, which takes the same run to 100 of 100. Adding a
User-Agentwas tested and made no difference — this is purely about rate. - Because a block is served as HTML rather than JSON, responses are parsed defensively; an HTML body is treated as a retryable block rather than crashing the run.
- The API returns
""rather thannullfor fields an object has no value for; those are normalized tonullso an empty field is not mistaken for a real value. - A query matching nothing throws rather than finishing with an empty dataset, which would otherwise look like a successful run that found nothing.