# Art Institute Painting Catalog - Object Metadata (`nexgensignal/artic-painting-catalog-records`) Actor

Art Institute of Chicago painting catalogue (artwork type Painting) as clean per-record metadata - title, artist\_display, date, medium, dimensions, department and public-domain flag. ~3,904 objects, CC0 metadata; no images. $0.05 per record.

- **URL**: https://apify.com/nexgensignal/artic-painting-catalog-records.md
- **Developed by:** [NexGen Signal](https://apify.com/nexgensignal) (community)
- **Categories:** Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $33.50 / 1,000 painting catalog records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Art Institute Painting Catalog - Object Metadata

The Art Institute of Chicago's **painting** catalogue as clean, per-object metadata - **one record per
painting**. Title, artist attribution, date, medium, dimensions, department, place of origin, classification
and the public-domain flag, released under CC0, with no images and no free-text description.

### What one record represents

The source is the **Art Institute of Chicago** public API (`api.artic.edu`), filtered to artwork type
**Painting** (`artwork_type_id=1`). Each record is **one painting**: its object id, title, the
`artist_display` historical attribution line, the display date, medium, dimensions, artwork type,
classification, department, place of origin, and the `is_public_domain` flag as a real boolean.

### Sample output

![Sample output — Art Institute Painting Catalog - Object Metadata](https://api.apify.com/v2/key-value-stores/IXCaMKjxSmUTLHhmq/records/artic-painting-catalog-records.png)

*Real rows from a live run of this actor (first 5 rows, selected columns).*

One full record from the same run, exactly as delivered:

```json
{
  "object_id": 129884,
  "title": "Starry Night and the Astronauts",
  "artist_display": "Alma Thomas\nAmerican, 1891–1978",
  "date_display": "1972",
  "medium_display": "Acrylic on canvas",
  "dimensions": "152.4 × 134.6 cm (60 × 53 in.)",
  "artwork_type": "Painting",
  "classification": "painting",
  "department": "Contemporary Art",
  "place_of_origin": "United States",
  "is_public_domain": false,
  "record_id": "129884",
  "source": "Art Institute of Chicago (api.artic.edu)",
  "source_dataset": "artworks/search",
  "licence": "Art Institute of Chicago (api.artic.edu). Artwork metadata released under CC0 (public-domain dedication). The free-text description field and all images/IIIF identifiers are excluded; no image, image URL or IIIF id is delivered.",
  "attribution": "Art Institute of Chicago (api.artic.edu)",
  "caveat": "Painting catalogue metadata (artwork type Painting, type id 1): title, artist_display, date, medium, dimensions, department, place of origin, classification and the is_public_domain flag. The full painting set is about 3,904 objects - under the source's 10,000-result cap, so the whole set is accessible in one query. artist_display is a historical attribution line; credit-line, provenance and all image/IIIF fields are excluded (CC0 covers metadata only).",
  "observed_at": "2026-09-25T17:17:46Z"
}
```

### Coverage and volume

The live painting set is **3,904 objects** (measured at build time from the API's pagination total). The
source caps a single query at 10,000 accessible results, and the painting set sits **comfortably under that
cap**, so the whole catalogue is accessible in one paged run - no partitioning is needed.

**Sol's Wave-3 index put this door at 3,904 records; measured live at build time the painting set is 3,904 -
matching the index exactly.**

The Actor pages the search API and stops as soon as your **Maximum records** cap is met.

### Licence and attribution

The Art Institute releases its artwork **metadata under CC0** (a public-domain dedication). The full notice
travels on every record:

> Art Institute of Chicago (api.artic.edu). Artwork metadata released under CC0 (public-domain dedication). The free-text description field and all images/IIIF identifiers are excluded; no image, image URL or IIIF id is delivered.

Attribution to the Art Institute of Chicago is stamped on every record. CC0 covers the metadata; images and
IIIF identifiers are a separate matter and are excluded entirely.

### Person-data policy

`artist_display` is a historical artist-attribution line (e.g. "Alma Thomas, American, 1891-1978") - a
catalogue attribution on the artwork, kept per the fleet's museum-metadata policy. Every other person-type
field is excluded: credit-line (donors), provenance and cataloguer fields are **never selected**, and no
image, image URL or IIIF identifier is ever delivered (the free-text description, which carries a separate
licence, is also excluded). A per-record assertion rejects any credit-line, provenance, donor, image or IIIF
field (verified with a planted-field test).

### Interpretation caveat

Painting catalogue metadata (artwork type Painting, type id 1): title, artist\_display, date, medium, dimensions, department, place of origin, classification and the is\_public\_domain flag. The full painting set is ~3,904 objects - under the source's 10,000-result cap, so the whole set is accessible in one query. artist\_display is a historical attribution line; credit-line, provenance and all image/IIIF fields are excluded.

Values are reproduced verbatim from the API; the Actor never rewrites a field. `is_public_domain` reflects
whether the museum considers the object itself in the public domain (distinct from the CC0 licence on the
metadata). `artist_display` is a display string, not a normalised artist record.

### Data quality and freshness

`is_public_domain` is delivered as a real boolean; the object id is a real number. Delivery is keyed on the
object id, so the dataset is safe to diff, deduplicate or upsert. Every run re-reads the live API, so the data
is as fresh as the museum publishes, and each record's `observed_at` stamp dates the snapshot. The run's
`RUN_RECEIPT` records how many records were delivered and charged.

### Provenance and compliance

Every run reads `api.artic.edu/robots.txt` at runtime; the gate result (URL, status, byte length, SHA-256 of
the policy) is written to the run's `RUN_RECEIPT`, and the artworks search path is confirmed crawlable before
any data request. The API is keyless. The Actor never bypasses a block or fetches through a mirror.

### Inputs

- **Maximum records** (`maxRecords`) - hard cap on painting records delivered and billed.

### Output

Records land in the Actor's default dataset and export as JSON, CSV, Excel or via the Apify API. A tabular
**overview view** surfaces object id, title, artist display, date, medium, department and the public-domain
flag.

### Fields in detail

The record leads with `object_id` and `title`, then `artist_display`, `date_display`, `medium_display`,
`dimensions`, `artwork_type`, `classification`, `department`, `place_of_origin` and the boolean
`is_public_domain`. The provenance block closes every record. Because the object id is the museum's stable
key, the dataset joins cleanly onto any system that references Art Institute object ids.

### Typical uses

Collection-data buyers and art-market teams use this cell to enrich painting inventories with clean,
CC0 museum metadata - one flat table of the Art Institute's paintings, keyed on the object id, ready to join
onto a catalogue or feed a collection-management model. Because the whole set is under the source cap, a single
run captures every painting; a scheduled run keeps a downstream inventory current as the museum updates its
records.

### Scaling and limits

Set **Maximum records** low to sample cheaply or high to pull the whole ~3,900-painting set. The Actor pages
the API and delivers incrementally, so memory stays flat and you are billed only for what is delivered. Because
the painting set sits under the 10,000-result cap, no year-range partition is needed here (unlike the larger
print catalogue). Re-run to pick up new acquisitions and catalogue updates.

### Paintings vs the print catalogue

This cell and the fleet's Art Institute print-catalogue cell draw the same museum API through the same recipe,
and stay distinct by artwork type: this one is `artwork_type_id=1` (Painting), the other is prints. The
practical difference is size - the print catalogue runs to tens of thousands of objects and needs a year-range
partition to get past the source's 10,000-result cap, whereas the painting set is under 4,000 and comes whole
in a single run. If you want the museum's full graphic-arts holdings you would run both and concatenate on the
shared field set; if you want paintings specifically, this cell is the clean slice.

### How the museum's fields map

`title` and `artist_display` are the museum's own catalogue values - `artist_display` is a single display line
that folds the artist's name, nationality and dates together (for example "Alma Thomas, American, 1891-1978"),
which is why it is kept as the historical attribution rather than parsed into a person record. `date_display`,
`medium_display` and `dimensions` are likewise display strings, faithful to the catalogue. `classification`
and `department` place the object within the museum's own taxonomy, and `place_of_origin` records geographic
origin. `is_public_domain` is the museum's judgment on the artwork itself and is separate from the CC0 licence
that covers this metadata.

### Data engineering

The record is flat, typed and keyed on the museum object id, so it loads without transformation. Because the
whole painting set fits under the source cap, a single run is complete and reproducible; a scheduled run diffs
cleanly against the last, surfacing new acquisitions and catalogue edits by the object id. No images or IIIF
identifiers are carried, so the rows stay small and the dataset stays purely textual metadata - fast to load,
cheap to store, and safe to redistribute under CC0. For a collection-management system or an art-market model,
that means the painting catalogue drops in as a ready reference table - no image handling, no licence
ambiguity, no reconciliation - and stays current with a single scheduled run keyed on the museum's own id.

### Sibling Actors

It sits beside the fleet's Art Institute print-catalogue cell (paintings vs prints, same door). It shares its engineering - the runtime robots gate, page/limit paging, push-then-charge
billing and verbatim-value discipline - with the fleet's Art Institute print-catalogue cell, from which it
stays distinct by artwork type (paintings vs prints).

# Actor input Schema

## `yearFrom` (type: `string`):

Optional start year. The source caps a single query at 10,000 results; set a year range to partition the full match set (e.g. 1800-1850) and reach beyond the cap.

## `yearTo` (type: `string`):

Optional end year (used with Year from).

## `maxRecords` (type: `integer`):

Maximum records delivered and billed (capped at the source's 10,000 accessible per query).

## Actor input object example

```json
{
  "maxRecords": 500
}
```

# Actor output Schema

## `results` (type: `string`):

The delivered Art Institute painting catalog record.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "maxRecords": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("nexgensignal/artic-painting-catalog-records").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "maxRecords": 500 }

# Run the Actor and wait for it to finish
run = client.actor("nexgensignal/artic-painting-catalog-records").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "maxRecords": 500
}' |
apify call nexgensignal/artic-painting-catalog-records --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nexgensignal/artic-painting-catalog-records"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/yZ2DQPH6WPHpfiarM/builds/KliwdvU6HgxUjCboC/openapi.json
