# Riseart.com Artist & Artwork Scraper (`artsiom_k/riseart-scraper`) Actor

Scrape Riseart.com artworks and artist profiles via the site's own public GraphQL search API, with built-in delta mode. No login required.

- **URL**: https://apify.com/artsiom\_k/riseart-scraper.md
- **Developed by:** [Artsiom Kunitsyn](https://apify.com/artsiom_k) (community)
- **Categories:**
- **Stats:** 1 total users, 0 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

## riseart-scraper

Scrapes both **artworks** and **artist profiles** from [Riseart.com](https://www.riseart.com), a UK-based
online art marketplace — via the site's own public GraphQL search API, no HTML scraping or sitemap
walking needed.

### Contents

- [Key features](#key-features)
- [Output](#output)
- [Input](#input)
- [Input examples](#input-examples)
- [Incremental (delta) mode](#incremental-delta-mode)
- [How to scrape Riseart.com](#how-to-scrape-riseartcom)
- [You might also like](#you-might-also-like)
- [FAQ](#faq)

### 🔑 Key features

- **Two entity types, one Actor.** Set `entityType` to `artworks` or `artists`.
- **No detail-page fetch at all.** Riseart's own public `searchArt`/`searchArtists` GraphQL queries
  already return every field this Actor emits, up to 100 items per request — there's no separate
  "discover a URL, then fetch its detail page" step like most scrapers need.
- **Fast, concurrent pagination.** Search-result pages are fetched in parallel (`concurrency` input,
  default 20) — validated live against Riseart's own endpoint with zero blocking at concurrency up
  to 50. A full, uncapped crawl of every artist (~1,625) finishes in under 5 seconds.
- **Multi-currency.** The `store` input picks which of Riseart's three regional stores prices are
  read from — `eu` (EUR), `uk` (GBP), or `us` (USD).
- **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.
- **`maxItems` defaults to 50** — a fast preview, and what keeps an unconfigured run within Apify's
  automated 5-minute QA check. Clear it (`null`) for a full crawl of the catalog (~48,800 artworks
  or ~1,625 artists as of this build).
- **Real per-artist rollup stats.** `entityType: "artists"` fetches each artist's complete artwork
  list (a real per-artist fetch, not a sample, sold pieces included) to compute `total_artworks`,
  `avg_price`, `for_sale_artworks`, `enquire_only_artworks`, and `sold_artworks`. A `minSoldArtworks`
  input filters what gets pushed down to artists with at least that many sales.
- **Full artwork detail for specific artists, sold pieces included.** Set `artistIds` on
  `entityType: "artworks"` to fetch every artwork for exactly those artists instead of the general
  catalog — the only way to get sold artworks with full detail (title, images, dimensions, price,
  medium/style/subject), since the general catalog never returns sold items at all. See
  [How to scrape Riseart.com](#how-to-scrape-riseartcom) for the two-run workflow this enables.

### 📋 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, or the
Output tab's **Artworks** / **Artists** views for a readable table.

**Example artwork record:**

```json
{
  "source": "riseart",
  "entity_type": "artworks",
  "external_id": "192404",
  "url": "https://www.riseart.com/art/192404/whispering-tides-by-paul-bennett",
  "title": "Whispering Tides",
  "artist_id": 2054,
  "artist_name": "Paul Bennett",
  "artist_alias": "paulbennett",
  "artist_url": "https://www.riseart.com/artist/2054/paulbennett",
  "price": 2755,
  "currency": "EUR",
  "can_buy": true,
  "can_rent": false,
  "sold": false,
  "stock": 1,
  "medium": "paintings",
  "style": "abstract",
  "subject": "landscapes",
  "width_cm": 80,
  "height_cm": 80,
  "depth_cm": 4,
  "unit": "CENTIMETER",
  "image_url": "https://d1ee3oaj5b5ueh.cloudfront.net/thumbs/1200x1500_processed_art_2026_08_ac409a7f-d3df-4d1c-b657-906ffe16be78-main-square.jpg",
  "change_type": "new"
}
```

**Example artist record:**

```json
{
  "source": "riseart",
  "entity_type": "artists",
  "external_id": "131449",
  "url": "https://www.riseart.com/artist/131449/carolin-kreutzer",
  "name": "Carolin Kreutzer",
  "alias": "carolin-kreutzer",
  "gender": "F",
  "website": "https://carolinkreutzer.de",
  "score": 549,
  "commissions": true,
  "birth_year": 1981,
  "birth_city": "Hamburg",
  "birth_country": "DE",
  "lives_city": "Stuttgart",
  "lives_country": "DE",
  "ships_country": "DE",
  "mediums": ["painters"],
  "total_artworks": 35,
  "avg_price": 1894.43,
  "currency": "EUR",
  "for_sale_artworks": 30,
  "enquire_only_artworks": 0,
  "sold_artworks": 5,
  "change_type": "new"
}
```

### 🔧 Input

| Field | Type | Default | Description |
|---|---|---|---|
| `entityType` | string | `artworks` | `artworks` or `artists`. |
| `store` | string | `eu` | Currency/region for artwork prices: `eu` (EUR), `uk` (GBP), `us` (USD). Ignored for `artists`. |
| `sort` | string | `featured` | Passed through to Riseart's own search API. Only affects discovery order, not coverage. |
| `rankingCountry` | string | — | Optional 2-letter country code affecting search ranking only. |
| `artistIds` | array | — | `artworks` only. List of Riseart artist ids — fetches every artwork for exactly those artists (sold pieces included) instead of the general catalog. See [How to scrape Riseart.com](#how-to-scrape-riseartcom). |
| `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 | `20` | How many result pages (100 items each) 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, EUR):**

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

**Full artist directory:**

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

**Artworks priced in GBP:**

```json
{ "entityType": "artworks", "store": "uk", "maxItems": null }
```

**Every artist with at least one sale, plus full detail on all their artworks (two runs):**

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

Take the `external_id` of every artist record this returns, then:

```json
{ "entityType": "artworks", "artistIds": ["120264", "118510", "131529"], "maxItems": null }
```

The second run returns every artwork (sold and unsold) for exactly those artists, with the same full
detail as a regular `artworks` run plus a real `sold` flag — something the general `artworks` catalog
can't give you, since it never returns sold items at all.

### 🔁 Incremental (delta) mode

`auto` mode does a full scan the first time it runs for a given `entityType`/`store` combination,
then only pushes new/changed items on later runs — cutting cost on repeat runs by not re-charging
for items that haven't changed. Only an uncapped run (no `maxItems` limit reached, and no page
errors) can detect delistings or update the baseline.

### 🌐 How to scrape Riseart.com

Riseart's frontend calls its own public GraphQL API directly (`https://graphql.riseart.com`) — this
Actor replicates exactly those calls (`searchArt`/`searchArtists`), the same requests your own
browser makes when you browse the site, just automated and exhaustive.

### 🔗 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.
- **[Kunsthaus ARTES Artist & Artwork Scraper](https://apify.com/artsiom_k/kunsthaus-artes-scraper)**
  — a seventh, independent art marketplace source (German gallery), with a real four-state
  availability signal (for sale, price-on-request, reserved, sold) read from the site's own
  schema.org microdata.
- **[Ars Mundi Artist & Artwork Scraper](https://apify.com/artsiom_k/ars-mundi-scraper)** — an
  eighth, independent art marketplace source (a sibling German gallery running the same underlying
  platform as Kunsthaus ARTES), also selling jewelry and decorative objects alongside
  paintings/sculptures.
- **[Artprice.com Artist & Artwork Scraper](https://apify.com/artsiom_k/artprice-scraper)** — a
  ninth, 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?**
Yes — `sold_artworks` on every artist record, computed from that artist's complete artwork list
(sold pieces included). Confirmed live at scale: a 40-artist random sample came back with 1,159
total artworks, 244 sold (21%), across 28/40 artists with at least one sale. Set `minSoldArtworks`
to only push artists who've sold at least that many pieces. Separately, `for_sale_artworks` counts
directly-buyable listings and `enquire_only_artworks` counts price-on-request ones — a genuine,
different-from-sold distinction (an enquire-only listing is still for sale, just not via direct
checkout).

**Can I get full detail (images, price, dimensions) on sold artworks?**
Yes, but only via `artistIds` — the general `entityType: "artworks"` catalog never returns sold
items at all (confirmed live: none of a known-sold artist's sold pieces show up in a normal search,
however it's sorted/filtered). Set `artistIds` to a specific list of artist ids and every artwork for
those artists comes back, sold pieces included with a real `sold` flag. The usual workflow: run
`entityType: "artists"` with `minSoldArtworks: 1` first to collect the artist ids you care about, then
feed those into an `artistIds`-scoped `artworks` run. See [Input examples](#input-examples).

**Why does the same artwork show a different price across runs if I only changed `store`?**
That's expected — `store` selects genuinely different regional pricing (EUR/GBP/USD), not just a
currency conversion, and delta mode scopes its baseline by `store` for exactly this reason: switching
it starts a fresh baseline rather than reporting every item as "changed".

**Does this need a proxy?**
No — no anti-bot friction was found anywhere on the endpoint this Actor uses.

# Actor input Schema

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

Scrape artworks or artist profiles, via Riseart's own public GraphQL search API. Each produces a different output shape (see dataset\_schema.json). Artist records include a real rollup (total\_artworks/avg\_price/for\_sale\_artworks/enquire\_only\_artworks/sold\_artworks).

## `store` (type: `string`):

Which of Riseart's three regional stores to price artworks in — confirmed live: "eu" = EUR, "uk" = GBP, "us" = USD. For entityType "artists", also prices the per-artist rollup stats (avg\_price/currency).

## `sort` (type: `string`):

Passed straight through to Riseart's own search API (e.g. "featured", "relevance"). Only affects the order items are discovered/pushed in, not which items are found — a full run covers the whole catalog regardless.

## `rankingCountry` (type: `string`):

Optional 2-letter country code passed to Riseart's search ranking (e.g. "AT", "US", "GB"). Affects result ordering only.

## `artistIds` (type: `array`):

Optional list of Riseart artist ids (the external\_id field on an artist record). When set and entityType is "artworks", fetches every artwork for exactly these artists — sold pieces included, unlike the general catalog — instead of the whole site. Pair this with an entityType="artists" run using minSoldArtworks to first collect the artist ids you want, e.g. everyone with at least one sale, then feed those ids in here for full per-artwork detail. Gets its own delta-mode tracking scope, independent of a general-catalog run. Ignored when entityType is "artists".

## `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 run covers Riseart's entire catalog (~48,800 artworks or ~1,625 artists as of this build) — raise this or clear it (set to null) for that.

## `minSoldArtworks` (type: `integer`):

Only push artist records with at least this many sold artworks (rollup field sold\_artworks). Set to 1 to skip artists who have never sold anything. Artists are still fully tracked internally either way (delta baseline, delisted-detection), so this only filters what gets pushed to the dataset, not the incremental logic. Ignored when entityType is "artworks".

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

"auto" (recommended): full scan on the first run for a given entityType/store, 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 an uncapped run can detect delistings or update the baseline.

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

How many search-result pages (100 items each) to fetch in parallel. Defaults to 20 — validated live against Riseart's own GraphQL endpoint with zero blocking at concurrency up to 50 (up to ~66 req/s in testing). Lower it only if you start seeing errors; there's no anti-bot reason to.

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

curl\_cffi browser TLS-impersonation target. Defaults to "chrome" internally, though no anti-bot friction was found anywhere on the endpoint this actor uses. Override only if that stops holding.

## `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",
  "store": "eu",
  "sort": "featured",
  "maxItems": 50,
  "minSoldArtworks": 0,
  "mode": "auto",
  "concurrency": 20,
  "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/riseart-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/riseart-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/riseart-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,artsiom_k/riseart-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/wRl5fdFKGSmAmiRDs/builds/BclHhymJomSWeXpqE/openapi.json
