Discover/Van Gogh Museum API
live

Van Gogh Museum APIvangoghmuseum.nl

Access the Van Gogh Museum collection via API. Search artworks, retrieve full metadata, multi-resolution images, provenance, and collection filters.

Endpoints
4
Updated
2mo ago

What is the Van Gogh Museum API?

The Van Gogh Museum API provides access to the museum's art collection through 4 endpoints, covering artwork search, detailed metadata retrieval, and filter discovery. Using get_artwork_detail, you can pull a single work's title, description, artist, dimensions, provenance, credits, catalogue numbers (f-number, jh-number), and image URLs at thumbnail, medium, and large resolutions — all in one response.

Try it
Search keyword to filter artworks (e.g. 'sunflowers'). Omitting returns the full collection.
Number of items to skip for pagination.
api.parse.bot/scraper/4aa2462d-3c4b-444f-b172-5aff7a992bd6/<endpoint>
Ready to send
Fill in the parameters and hit sign in to send to see live response data here.
Call it over HTTPgrab a free API key at signup
curl -X GET 'https://api.parse.bot/scraper/4aa2462d-3c4b-444f-b172-5aff7a992bd6/get_collection?query=sunflowers&offset=0' \
  -H 'X-API-Key: $PARSE_API_KEY'
Python SDK · recommended

Typed, relational, agent-ready

A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.

  • Fully typed · autocompletes
  • Objects link to objects
  • Typed errors & pagination

Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:

uv add parse-sdk
uv run parse init
uv run parse add --marketplace vangoghmuseum-nl-api

uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.

"""
Van Gogh Museum Collection API Client
Get your API key from: https://parse.bot/settings
"""

import os
import requests
from typing import Any, Dict, List, Optional


class ParseClient:
    """Client for interacting with the Van Gogh Museum Collection API via Parse."""

    def __init__(self, api_key: Optional[str] = None):
        """
        Initialize the Parse client.

        Args:
            api_key: API key for authentication. If not provided, reads from PARSE_API_KEY env var.

        Raises:
            ValueError: If API key is not provided and PARSE_API_KEY env var is not set.
        """
        self.base_url = "https://api.parse.bot"
        self.scraper_id = "4aa2462d-3c4b-444f-b172-5aff7a992bd6"
        self.api_key = api_key or os.getenv("PARSE_API_KEY")

        if not self.api_key:
            raise ValueError("API key not provided and PARSE_API_KEY env var not set")

    def _call(self, endpoint: str, method: str = "POST", **params) -> Dict[str, Any]:
        """
        Make an API call to the Parse endpoint.

        Args:
            endpoint: The endpoint name (e.g., "get_collection")
            method: HTTP method ("GET" or "POST")
            **params: Query/body parameters for the endpoint

        Returns:
            Response JSON as dictionary

        Raises:
            requests.RequestException: If the API call fails
        """
        url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
        headers = {
            "X-API-Key": self.api_key,
            "Content-Type": "application/json"
        }

        if method.upper() == "GET":
            response = requests.get(url, headers=headers, params=params)
        elif method.upper() == "POST":
            response = requests.post(url, headers=headers, json=params)
        else:
            raise ValueError(f"Unsupported HTTP method: {method}")

        response.raise_for_status()
        return response.json()

    def get_collection(
        self,
        query: str = "",
        offset: int = 0
    ) -> Dict[str, Any]:
        """
        Browse or search the museum collection.

        Args:
            query: Search keyword to filter artworks (optional)
            offset: Result offset for pagination

        Returns:
            Dictionary containing items, count, and offset
        """
        return self._call("get_collection", method="GET", query=query, offset=offset)

    def search_artworks(
        self,
        query: str,
        offset: int = 0
    ) -> Dict[str, Any]:
        """
        Search for artworks by keyword.

        Args:
            query: Search keyword (required)
            offset: Result offset for pagination

        Returns:
            Dictionary containing items, count, and offset
        """
        return self._call("search_artworks", method="GET", query=query, offset=offset)

    def get_artwork_detail(self, artwork_id: str) -> Dict[str, Any]:
        """
        Retrieve full details for a single artwork by its ID.

        Args:
            artwork_id: Artwork ID (e.g., 's0031V1962')

        Returns:
            Dictionary containing full artwork details including metadata and images
        """
        return self._call("get_artwork_detail", method="GET", artwork_id=artwork_id)

    def get_collection_filters(self) -> Dict[str, Any]:
        """
        Retrieve available filter categories and their values for the collection.

        Returns:
            Dictionary containing list of available filters with categories and values
        """
        return self._call("get_collection_filters", method="GET")


def main():
    """Practical workflow demonstrating the Van Gogh Museum Collection API."""
    # Initialize client
    client = ParseClient()

    print("=" * 80)
    print("VAN GOGH MUSEUM COLLECTION EXPLORER")
    print("=" * 80)

    # Step 1: Get available filters to understand what we can search
    print("\n[STEP 1] Fetching available collection filters...")
    try:
        filters_response = client.get_collection_filters()
        filters_data = filters_response.get("data", {})
        filters_list = filters_data.get("filters", [])
        print(f"✓ Available filter categories: {len(filters_list)}")
        for filter_item in filters_list[:3]:
            category = filter_item.get("category", "Unknown")
            total_options = filter_item.get("total_options", 0)
            print(f"  - {category} ({total_options} options)")
    except Exception as e:
        print(f"✗ Error fetching filters: {e}")
        return

    # Step 2: Search for artworks using a specific query
    search_term = "Sunflowers"
    print(f"\n[STEP 2] Searching for artworks matching '{search_term}'...")
    try:
        search_results = client.search_artworks(query=search_term, offset=0)
        search_data = search_results.get("data", {})
        total_count = search_data.get("count", 0)
        items = search_data.get("items", [])

        if total_count == 0:
            print(f"✗ No artworks found for '{search_term}'")
            return

        print(f"✓ Found {total_count} artwork(s)")
        print(f"  Displaying first {min(3, len(items))} results...\n")
    except Exception as e:
        print(f"✗ Error during search: {e}")
        return

    # Step 3: Process each search result and fetch detailed information
    detailed_artworks = []
    for idx, item in enumerate(items[:3], 1):
        artwork_id = item.get("id")
        title = item.get("title", "Unknown")
        creator = item.get("creator", "Unknown")
        position = item.get("position", "N/A")

        print(f"[Artwork {idx}] {title}")
        print(f"  ID: {artwork_id}")
        print(f"  Creator: {creator if creator else 'Unknown'}")
        print(f"  Position in collection: {position}")

        try:
            # Fetch detailed information for this artwork
            artwork_detail_response = client.get_artwork_detail(artwork_id)
            artwork_detail = artwork_detail_response.get("data", {})
            detailed_artworks.append(artwork_detail)

            # Display full details
            description = artwork_detail.get("description", "No description available")
            print(f"  Description: {description[:120]}{'...' if len(description) > 120 else ''}")

            # Display metadata
            metadata = artwork_detail.get("metadata", {})
            if metadata:
                artist = metadata.get("artist", "Unknown")
                dimensions = metadata.get("dimensions", "Unknown")
                f_number = metadata.get("f-number", "N/A")
                print(f"  Artist: {artist}")
                if dimensions:
                    print(f"  Dimensions: {dimensions}")
                if f_number != "N/A":
                    print(f"  F-Number: {f_number}")

            # Display tags if available
            tags = artwork_detail.get("tags", [])
            if tags:
                print(f"  Tags: {', '.join(tags)}")

            # Display image information
            images = artwork_detail.get("images", [])
            if images:
                image = images[0]
                thumbnail_url = image.get("thumbnail", "N/A")
                medium_url = image.get("medium", "N/A")
                large_url = image.get("large", "N/A")
                print(f"  Image resolutions available:")
                print(f"    - Thumbnail: {thumbnail_url[:50]}...")
                print(f"    - Medium: {medium_url[:50]}...")
                print(f"    - Large: {large_url[:50]}...")

        except Exception as e:
            print(f"  ✗ Error fetching details: {e}")

        print()

    # Step 4: Demonstrate pagination for larger result sets
    if total_count > 3:
        print("[STEP 3] Demonstrating pagination...")
        try:
            next_page_results = client.search_artworks(query=search_term, offset=3)
            next_page_data = next_page_results.get("data", {})
            next_items = next_page_data.get("items", [])
            next_offset = next_page_data.get("offset", 3)

            if next_items:
                print(f"✓ Retrieved next page (offset={next_offset})")
                print(f"  Results {next_offset + 1}-{next_offset + len(next_items)} of {total_count}:")
                for item in next_items[:2]:
                    title = item.get("title", "Unknown")
                    print(f"    - {title}")
            else:
                print("  No more results available")
        except Exception as e:
            print(f"✗ Error fetching next page: {e}")

    # Step 5: Browse full collection without search
    print("\n[STEP 4] Browsing full collection (first page)...")
    try:
        collection_results = client.get_collection(offset=0)
        collection_data = collection_results.get("data", {})
        all_items = collection_data.get("items", [])
        collection_count = collection_data.get("count", 0)

        print(f"✓ Total items in collection: {collection_count}")
        print(f"  Showing first {min(2, len(all_items))} items:")
        for item in all_items[:2]:
            title = item.get("title", "Unknown")
            item_id = item.get("id", "Unknown")
            print(f"    - {title} (ID: {item_id})")
    except Exception as e:
        print(f"✗ Error browsing collection: {e}")

    # Step 6: Summary
    print("\n" + "=" * 80)
    print(f"SUMMARY: Successfully retrieved detailed information for {len(detailed_artworks)} artwork(s)")
    print("=" * 80)


if __name__ == "__main__":
    main()
All endpoints · 4 totalmissing one? ·

Browse or search the museum collection. Returns a paginated list of artworks with basic info including title, creator, image URL, and link to the artwork page.

Input
ParamTypeDescription
querystringSearch keyword to filter artworks (e.g. 'sunflowers'). Omitting returns the full collection.
offsetintegerNumber of items to skip for pagination.
Response
{
  "type": "object",
  "fields": {
    "count": "integer total number of items returned in this response",
    "items": "array of artwork summary objects with id, title, creator, url, image_url, and position",
    "offset": "integer offset used in this request"
  },
  "sample": {
    "data": {
      "count": 11,
      "items": [
        {
          "id": "s0031V1962",
          "url": "https://www.vangoghmuseum.nl/en/collection/s0031V1962",
          "title": "Sunflowers",
          "creator": "",
          "position": "1",
          "image_url": "https://iiif.micr.io/TZCqF/full/200"
        }
      ],
      "offset": 0
    },
    "status": "success"
  }
}

About the Van Gogh Museum API

Collection Browsing and Search

Two endpoints handle discovery: get_collection and search_artworks. Both return paginated lists of artwork summaries — each item includes an id, title, creator, url (link to the museum page), image_url, and position. get_collection accepts an optional query parameter; omitting it returns the full collection. search_artworks requires a query string (e.g. 'self-portrait', 'night'). Both support an offset integer for pagination, and both return a count field reflecting how many items came back in the current page.

Artwork Detail

get_artwork_detail takes a single required artwork_id — obtainable from any collection or search result — and returns the full record for that work. The metadata object contains structured fields: artist, dimensions, provenance, credits, object_number, f-number, and jh-number (the standard Van Gogh catalogue references). The images array provides multiple resolution variants: thumbnail, medium, and large URLs, plus an id per image. The tags array and free-text description field round out the record.

Filter Discovery

get_collection_filters takes no inputs and returns all available filter categories for the collection. Each category object includes a category label, a param_name for use in queries, a total_options count, and a values array where each entry has a name, value, and result count. Documented categories include On view, Artist, Location, Year, Object type, Genre, and Sub-collections — useful for building faceted browsing UIs or scoping batch requests to a specific artist or object type.

Reliability & maintenance

The Van Gogh Museum API is a managed, monitored endpoint for vangoghmuseum.nl — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when vangoghmuseum.nl changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.

This isn't an official vangoghmuseum.nl API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.

Will this API break when the source site changes?+
It's built not to. Every endpoint is health-checked on a schedule with automated test probes. When the source site changes and a check fails, the API is automatically queued for repair and re-verified — that's the self-healing layer. Each API page shows when its endpoints were last verified. And because marketplace APIs are shared, any fix reaches everyone using it.
Is this an official API from the source site?+
No — Parse APIs are independent, managed REST wrappers over publicly available data. That is the point: where a site has no official API (or only a limited one), Parse gives you a maintained, monitored endpoint for that data and keeps it working as the site changes — so you get a stable contract over a source that never promised one.
Can I fix or extend this API myself if I need a new endpoint or field?+
Yes — and you don't have to wait on us. This API was generated by the Parse agent, which stays attached. Describe the change in plain English ("add an endpoint that returns reviews", "fix the price field") in the revise box on the API page or via the revise_api MCP tool, and the agent rebuilds it against the live site in minutes. Contributing the change back to the public API is free.
What happens if I call an endpoint that has an issue?+
Errors are machine-readable: a bad call returns a clean status with the list of available endpoints and a repair hint, so an agent (or you) can recover or trigger a fix instead of failing silently. Confirmed failures feed the automatic repair queue.
Common use cases
  • Building a searchable gallery app using search_artworks results with image_url and title fields.
  • Aggregating Van Gogh catalogue data by pulling f-number and jh-number from get_artwork_detail metadata.
  • Rendering faceted collection browsers using filter categories and counts from get_collection_filters.
  • Displaying provenance and credits for individual works in an academic or educational context.
  • Paginating through the full collection with get_collection and offset to build a local artwork index.
  • Feeding multi-resolution artwork images into a print-on-demand or digital exhibition pipeline using large image URLs.
  • Filtering works by object type or year using values returned from get_collection_filters to scope targeted queries.
Pricing & limitsSee full pricing →
TierPriceCredits/monthRate limit
Free$0/mo1005 req/min
Hobby$30/mo1,00020 req/min
Developer$100/mo5,000100 req/min

One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.

Frequently asked questions
Does the Van Gogh Museum have an official developer API?+
The Van Gogh Museum does not publish a public developer API with documented access and keys. This Parse API provides structured access to the collection data available on vangoghmuseum.nl.
What catalogue identifiers does `get_artwork_detail` return?+
The metadata object includes f-number (the De la Faille catalogue number) and jh-number (the Jan Hulsker catalogue number), alongside object_number, dimensions, provenance, and credits. These are the standard references used in Van Gogh scholarship.
Does the API cover letters, drawings, and prints, or only paintings?+
The collection includes paintings, drawings, and letters — Van Gogh's complete holdings as represented on the museum site. The get_collection_filters endpoint exposes an Object type category that breaks down available types and their counts.
Does the API expose exhibition schedules or visitor information?+
Not currently. The API covers collection data: artworks, metadata, images, and collection filters. Exhibition schedules, ticketing, and visitor information are not included. You can fork this API on Parse and revise it to add an endpoint targeting that content.
How does pagination work across endpoints?+
Both get_collection and search_artworks accept an offset integer parameter to skip a given number of items. Each response returns a count of items in that page and echoes back the offset used, so you can step through the collection in batches.
Page content last updated . Spec covers 4 endpoints from vangoghmuseum.nl.
Related APIs in EntertainmentSee all →
artsy.net API
Browse and search across 300,000+ artists to discover detailed profiles with biographies, nationalities, career insights, and artwork counts. Find artists alphabetically or by name to explore their complete creative background and body of work.
lacma.org API
Search LACMA's art collection, discover current and upcoming exhibitions, browse events and programs, and view detailed artwork information all from one place. Plan your museum visit with access to exhibition details, visitor information, and the complete catalog of artworks on display.
riseart.com API
Search and explore artworks by title, artist, or style, then view detailed information and high-quality images of paintings and artist portfolios from Rise Art's curated collection. Discover new artists and browse their complete galleries to find pieces that match your taste.
fineartamerica.com API
Search and discover millions of artworks by style, medium, and artist, then browse detailed artist profiles and portfolios to connect directly with creators. Reach out to artists through integrated contact forms to inquire about commissions, purchases, or collaborations.
vcg.com API
Search and discover millions of stock images from Visual China Group's vast media library, view trending content and popular search terms, and find visually similar images to match your creative needs. Access detailed image metadata, thumbnails, and brand information to power your content curation, design projects, or visual research workflows.
ticketswap.nl API
ticketswap.nl API
dpm.org.cn API
Search and explore the Palace Museum's vast collection of artifacts organized by category and dynasty, then view detailed information about specific items. Discover historical objects spanning different periods and classifications to learn about the museum's treasures.
invaluable.com API
Search and browse fine art auction listings from Invaluable.com, discovering items by artist, auction house, or upcoming lots. Get detailed information about artworks, artists, and auction house catalogs to track pieces and stay informed about upcoming sales.