# Ars Mundi Artist & Artwork Scraper (`artsiom_k/ars-mundi-scraper`) Actor

Scrape Arsmundi.de artworks (paintings/sculptures/jewelry) and artist profiles, with built-in delta mode. No login required.

- **URL**: https://apify.com/artsiom\_k/ars-mundi-scraper.md
- **Developed by:** [Artsiom Kunitsyn](https://apify.com/artsiom_k) (community)
- **Categories:** Other, E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## ars-mundi-scraper

Scrapes both **artworks** (paintings/sculptures/jewelry) and **artist profiles** from
[Arsmundi.de](https://www.arsmundi.de), a German art gallery/marketplace, via the site's own
sitemap and real schema.org microdata — no login required.

### Contents

- [Key features](#key-features)
- [Output](#output)
- [Input](#input)
- [Input examples](#input-examples)
- [Incremental (delta) mode](#incremental-delta-mode)
- [You might also like](#you-might-also-like)
- [FAQ](#faq)

### 🔑 Key features

- **Two entity types, one Actor.** Set `entityType` to `artworks` or `artists`.
- **A real availability signal.** Every artwork is classified as `for_sale` (has a price),
  `price_on_request` (price-on-request, still genuinely for sale), `reserved` (temporarily
  unavailable), or `sold` — the same real signal confirmed on this Actor's sibling
  `kunsthaus-artes-scraper` (same underlying platform); see the FAQ below for its confirmed status
  on this specific site.
- **Rich, structured fields from real schema.org microdata** — SKU, artist name, dimensions
  (mm), GTIN-13 barcode, and a pipe-delimited edition/medium/framing summary, all read directly
  from the page's own structured data rather than scraped from display text.
- **Delta mode built in.** Every run classifies each item as `new`, `changed`, `unchanged`, or
  `delisted` against a persisted baseline — pay for what changed, not a full re-scrape every time.
- **Confirmed-dead listings are never re-fetched.** A removed artwork or artist returns a plain
  HTTP 404 on this site — tracked in a persisted registry so a future run skips it without a
  wasted request.
- **`maxItems` defaults to 50** — a fast, cheap preview, and what keeps an unconfigured run within
  Apify's automated 5-minute QA check. Clear it (`null`) for a full crawl (~2,700 artworks or ~900
  artists as of this build).

**Not included yet:** artist records are base bio data only (name + short biography) — no artwork
rollup (total/avg price/sold count). See the FAQ below for why.

### 📋 Output

One dataset item per artwork or artist, depending on `entityType` — see
[`.actor/dataset_schema.json`](.actor/dataset_schema.json) for the full field list.

**Example artwork record:**

```json
{
  "source": "arsmundi",
  "entity_type": "artworks",
  "external_id": "IN-688439.R1",
  "url": "https://www.arsmundi.de/salvador-dali-bild-die-meditative-rose-1958-gerahmt-688439-r1/",
  "title": "Bild \"Die meditative Rose\" (1958), gerahmt",
  "artist_name": "Salvador Dalí",
  "artist_url": "https://www.arsmundi.de/kuenstler/dali-salvador/",
  "artist_id": "9999e6142ed82e47dbf87be816301147",
  "price": 480,
  "currency": "EUR",
  "availability_status": "for_sale",
  "width_mm": 610,
  "height_mm": 720,
  "gtin13": "4044991560613",
  "image_url": "https://www.arsmundi.de/thumbnails/g0/85/d6/1619633493/688439.R1_1_320x320.jpg",
  "change_type": "new"
}
```

**Example artist record:**

```json
{
  "source": "arsmundi",
  "entity_type": "artists",
  "external_id": "0199abc1234de5f6a7b8c9d0e1f2a3b4",
  "url": "https://www.arsmundi.de/kuenstler/heber-peter/",
  "name": "Peter Heber",
  "bio": "Peter Heber ...",
  "change_type": "new"
}
```

### 🔧 Input

| Field | Type | Default | Description |
|---|---|---|---|
| `entityType` | string | `artworks` | `artworks` or `artists`. |
| `startUrls` | array | — | Specific artwork/artist URLs to scrape directly instead of the full sitemap. |
| `maxItems` | integer | `50` | Stop after pushing this many items. Set to `null` for a full crawl. |
| `mode` | string | `auto` | `auto` / `full` / `incremental` — see [Incremental mode](#incremental-delta-mode). |
| `concurrency` | integer | `12` | How many detail pages to fetch in parallel. |
| `impersonate` | string | `chrome` | curl\_cffi TLS-impersonation target. |
| `proxyConfiguration` | object | off | Apify Proxy config — not needed; no anti-bot friction found. |

### 📥 Input examples

**Default preview (50 artworks):**

```json
{ "entityType": "artworks" }
```

**Full artist directory:**

```json
{ "entityType": "artists", "maxItems": null }
```

### 🔁 Incremental (delta) mode

`auto` mode does a full scan the first time it runs for a given `entityType`/scope, then only pushes
new/changed items on later runs. Only an uncapped, unscoped run (no `maxItems` limit reached, no
`startUrls`, no item errors) can detect delistings or update the baseline.

### 🔗 You might also like

- **[SaatchiArt Artist & Artwork Scraper](https://apify.com/artsiom_k/saatchiart-scraper)** — the
  same entity-type design pointed at a first, independent art marketplace, with a real per-artist
  rollup (avg price, medium mix, sold count) computed from an artist's full catalog.
- **[Artmajeur Artist & Artwork Scraper](https://apify.com/artsiom_k/artmajeur-scraper)** — a
  second independent art marketplace source, same rollup-stats design.
- **[Artsper Artist & Artwork Scraper](https://apify.com/artsiom_k/artsper-scraper)** — a third,
  independent art marketplace source, same design.
- **[Artfinder Artist & Artwork Scraper](https://apify.com/artsiom_k/artfinder-scraper)** — a
  fourth, independent art marketplace source, same design.
- **[Artsy Artist, Artwork & Gallery Scraper](https://apify.com/artsiom_k/artsy-scraper)** — a
  fifth, independent art marketplace source, plus a genuine dealer/gallery angle (real
  represented-artist rollups per gallery) this collection doesn't otherwise have.
- **[Bluethumb Artist & Artwork Scraper](https://apify.com/artsiom_k/bluethumb-scraper)** — a
  sixth, independent art marketplace source (Australia's largest), with real per-artist
  sold/available/total counts read from a single profile-page fetch, no rollup fan-out needed.
- **[Riseart Artist & Artwork Scraper](https://apify.com/artsiom_k/riseart-scraper)** — a seventh,
  independent art marketplace source, built entirely on the site's own public GraphQL search API
  (no HTML scraping, no per-item detail fetch), with a real per-artist rollup (total artworks, avg
  price, for-sale vs. enquire-only split).
- **[Kunsthaus ARTES Artist & Artwork Scraper](https://apify.com/artsiom_k/kunsthaus-artes-scraper)**
  — an eighth, independent art marketplace source (a sibling German gallery running the same
  underlying platform as this Actor).
- **[Artprice.com Artist & Artwork Scraper](https://apify.com/artsiom_k/artprice-scraper)** — a
  tenth, independent art marketplace source, built on Artprice.com's own public unauthenticated
  JSON APIs (artist directory + current marketplace listings), with real per-artist rollup stats
  and multi-currency pricing (EUR/USD/GBP/CNY/BTC/ETH) on every artwork.

### ❓ FAQ

**Does this Actor tell me how many artworks an artist has sold?**
No. This Actor's sibling `kunsthaus-artes-scraper` (the same underlying platform) investigated this
thoroughly and confirmed the site has no per-artist "all works by this artist" listing anywhere —
not on the bio page, not through the generic listing widgets, and not through the platform's own
dedicated "artist directory" component either (referenced on the page but never actually rendered
there). Given both sites share the identical page template, the same conclusion is expected to hold
here; `entityType: "artists"` gives base bio data only.

**Is the "reserved"/"sold"/"price-on-request" status confirmed on this specific site?**
Partially. `for_sale` is confirmed on many real Ars Mundi listings. The other three states use the
same parsing logic as this Actor's sibling `kunsthaus-artes-scraper` (confirmed to run on the same
underlying platform, same page template, same German status text) — but a live sample of 140 real
product pages during this build, including a targeted sample of well-known/high-value artists, did
not turn up a real example of any of them on Ars Mundi specifically. They may be rarer here, or the
current catalog may simply not have one right now. Reported honestly rather than presented as fully
verified — if you spot one, the field is there and should be correct, but treat it as
less-battle-tested than `for_sale`.

**Why do some artists have no bio?**
A real, confirmed absence on the site itself: well-known artists (e.g. Friedensreich Hundertwasser)
have a real biography block on their profile page, but many lesser-known artists simply don't —
the block is entirely absent from the page, not just empty. A real 20-artist sample during this
build came back with 17/20 missing a bio for exactly this reason.

**Why do some artworks have no artist\_url or dimensions?**
Both are real, confirmed absences on the site itself, not scraping gaps: some artists don't have a
dedicated bio page linked from their artwork pages, and some listings describe their size only in
free text (`short_info`/`description`), not as separate structured width/height fields.

**Does this need a proxy?**
No — no anti-bot friction was found anywhere on this site while building this Actor.

# Actor input Schema

## `entityType` (type: `string`):

Scrape artworks (paintings/sculptures/jewelry) or artist profiles. Each produces a different output shape (see dataset\_schema.json). Artist records are base bio data only — no artwork rollup (confirmed on the sibling kunsthaus-artes-scraper, same underlying platform, that this site has no per-artist full-catalog listing to build one from; see README FAQ).

## `startUrls` (type: `array`):

Optional list of specific Ars Mundi artwork (https://www.arsmundi.de/{slug}-{sku}/) or artist (https://www.arsmundi.de/kuenstler/{slug}/) URLs to scrape directly, instead of discovering via the full site sitemap — use whichever kind matches entityType. A startUrls-scoped run cannot detect delistings or update the incremental baseline.

## `maxItems` (type: `integer`):

Stop after pushing this many dataset items. Defaults to 50 — a fast, cheap preview, and what keeps an unconfigured run within Apify's automated 5-minute QA check. A full, uncapped sitemap crawl covers the entire site (~2,700 artworks, or ~900 artists as of this build) — raise this or clear it (set to null) for that.

## `mode` (type: `string`):

"auto" (recommended): full scan on the first run for a given entityType/scope, incremental (new/changed only) afterwards. "full": always push every item and refresh the baseline — schedule this periodically to catch delistings. "incremental": always push only new/changed items. Only a plain, unscoped sitemap crawl (no startUrls) can detect delistings or update the baseline.

## `concurrency` (type: `integer`):

How many artwork/artist detail pages to fetch in parallel. Defaults to 12 — validated live against arsmundi.de with no blocking signal at concurrency up to 25 (one transient-timeout blip on a single test pass, not reproduced on a retest). Lower it only if you start seeing errors.

## `impersonate` (type: `string`):

curl\_cffi browser TLS-impersonation target. Defaults to "chrome" internally, though no anti-bot friction was found anywhere on this site while building this actor.

## `proxyConfiguration` (type: `object`):

Apify Proxy configuration. Leave off unless you start seeing blocks from your own IP reputation — no anti-bot friction was found while building this actor.

## Actor input object example

```json
{
  "entityType": "artworks",
  "maxItems": 50,
  "mode": "auto",
  "concurrency": 12,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("artsiom_k/ars-mundi-scraper").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("artsiom_k/ars-mundi-scraper").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 '{}' |
apify call artsiom_k/ars-mundi-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,artsiom_k/ars-mundi-scraper"
        }
    }
}

```

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/aTKRrZ0FOaxhNdE5d/builds/JMWYP0TS4XQ6llZbt/openapi.json
