Search
Introduction
This tutorial walks you through how to search the Rijksmuseum collection using the Search API.
The documentation page explains the available endpoints, parameters, and technical specifications. This tutorial focuses on something different:
How do you actually use the Search API in a real workflow?
After completing this tutorial, you will understand:
- when the Search API is the right choice
- how to make your first request
- how to interpret JSON responses
- how pagination works with
pageToken - how to resolve identifiers into full object records
- how to build a simple search workflow
When should you use the Search API?
The Search API is designed for querying the collection based on specific characteristics.
Use the Search API when you want to:
- search for objects by creator, type, material, technique, ...
- find objects created in a specific period
- filter objects by title, description, or subject
- check whether a digital image is available
- look up an object by its object number
The Search API is not the best choice when you need to:
- download complete datasets
- synchronize metadata regularly
- build a local copy of collection data
In those cases, OAI-PMH may be more appropriate.
How the Search API works
The Search API works differently from OAI-PMH. You do not harvest batches of records. Instead, you send a query and receive a list of matching identifiers.
A typical workflow looks like this:
- Build a query → combine one or more search parameters
- Send a request → retrieve a page of matching identifiers
- Paginate → follow
nextto retrieve additional pages - Resolve → use the identifiers to retrieve full object records
Think of the Search API as a discovery layer: it tells you what exists, not what it contains. It returns identifiers, which you then resolve separately to retrieve complete records.
Step-by-step tutorial
Step 1 — Make your first request
The API is available at:
https://data.rijksmuseum.nl/search/collection
No API key is required. Requesting this URL without parameters returns the first 100 items of the entire collection. The response is raw JSON, intended for programmatic use — opening it directly in a browser may look overwhelming at first.
A simple search looks like this:
https://data.rijksmuseum.nl/search/collection?type=painting&creator=Rembrandt
This returns paintings associated with Rembrandt. Parameters are partial keyword matches, so Rembrandt also matches Rembrandt van Rijn.
Step 2 — Explore the available parameters
The API supports a range of query parameters. All parameters are optional and can be combined using &. Multiple parameters are treated as AND — for example, type=painting&material=oil+paint returns only objects that are both a painting and made with oil paint.
To search for multiple values within the same parameter, repeat the parameter. For example, material=oil+paint&material=canvas returns objects that contain both oil paint and canvas . This is also treated as AND.
| Parameter | Description |
|---|---|
creator | Creator name, such as Rembrandt van Rijn |
type | Object type, such as painting |
material | Material, such as canvas |
technique | Technique, such as etching |
title | Title keyword, such as Night Watch |
description | Keyword in the object description |
creationDate | Year or period, such as 1642 or 16?? |
aboutActor | Person or group depicted in the object |
objectNumber | Object number, such as SK-C-5 |
memberOfSetId | Set identifier |
imageAvailable | true or false |
Dutch terms are always supported. English terms are supported where translations are available, but coverage is partial — many thesaurus terms do not have an English equivalent. If a query doesn’t return expected results, switch to Dutch terms — coverage is significantly better.
For objectNumber and creationDate, wildcard characters are supported:
*matches any number of characters:SK-C-5*matchesSK-C-5,SK-C-50, andSK-C-501?matches exactly one character:16??matches1642and1600, but not167
Step 3 — Interpret the response
The API returns a JSON response based on the Linked Art Search specification:
{
"@context": "https://linked.art/ns/v1/search.json",
"id": "https://data.rijksmuseum.nl/search/collection?type=painting&material=oil+paint",
"type": "OrderedCollectionPage",
"partOf": {
"id": "https://data.rijksmuseum.nl/search/collection?type=painting&material=oil+paint",
"type": "OrderedCollection",
"totalItems": 4819,
"first": {
"id": "https://data.rijksmuseum.nl/search/collection?type=painting&material=oil+paint",
"type": "OrderedCollectionPage"
},
"last": {
"id": "https://data.rijksmuseum.nl/search/collection?type=painting&material=oil+paint&pageToken=eyJ0b2tlbiI6ICJodHRwczovL2lkLnJpamtzbXVzZXVtLm5sLzIwMDkwNTYwIn0",
"type": "OrderedCollectionPage"
}
},
"next": {
"id": "https://data.rijksmuseum.nl/search/collection?type=painting&material=oil+paint&pageToken=eyJ0b2tlbiI6ICJodHRwczovL2lkLnJpamtzbXVzZXVtLm5sLzIwMDEwNzg2MCJ9",
"type": "OrderedCollectionPage"
},
"orderedItems": [
{ "id": "https://id.rijksmuseum.nl/200100988", "type": "HumanMadeObject" },
{ "id": "https://id.rijksmuseum.nl/200104600", "type": "HumanMadeObject" },
{ "id": "https://id.rijksmuseum.nl/200105887", "type": "HumanMadeObject"},
]
}
The orderedItems array contains up to 100 results per page.
The key fields are:
id— the full search request URL for the current page of resultspartOf.totalItems— total number of matching objectspartOf.first.idandpartOf.last.id— URLs for the first and last pages of resultsnext.id— URL for the next page of results, including thepageTokenfor paginationorderedItems— list of matching objects, each with a Linked Open Data identifier (id) and type
The identifiers in orderedItems are not full object records. These identifiers must be resolved separately to retrieve full metadata (see Step 5).
Step 4 — Pagination
Each response page contains up to 100 results. If more results are available, a next.id field is included.
To retrieve the next page, request the URL in next.id:
Continue following the next.id field until it is no longer present in the response to paginate through results.
Step 5 — Resolve identifiers
The identifiers returned in orderedItems[].id point to full object records. To resolve an identifier, open or request the URI. The response will contain complete metadata such as title, creator, date, and description.
The Search API always returns responses in Linked Art format, but when resolving identifiers you can request different metadata formats by adding ?_profile= followed by the token to the URI. For example, the following URL returns the record in EDM format:
https://data.rijksmuseum.nl/200100988?_profile=edm
The following formats are available:
| Format | Token |
|---|---|
| Dublin Core | dc |
| Europeana Data Model | edm |
| OAI Dublin Core | oai_dc |
| Linked Art | la |
| Linked Art (framed) | la-framed |
| EDM (framed) | edm-framed |
See the Resolving identifiers example in Step 6 for a practical example.
Alternatively, content negotiation can also be performed using HTTP headers. See the Linked Data Resolver documentation for details.
Step 6 — Python examples
Basic example
Before running this script, make sure the required library is installed:
pip install requests
The example below searches for paintings made with oil paint that have a digital image available, and prints their identifiers.
import requests
# Define the search endpoint and parameters
url = "https://data.rijksmuseum.nl/search/collection"
params = {
"imageAvailable": "true",
"type": "painting",
"material": "oil paint"
}
# Fetch and parse the response
response = requests.get(url, params=params)
data = response.json()
# Print the total number of results and the identifiers
print(f"Total results: {data['partOf']['totalItems']}")
print()
for item in data['orderedItems']:
print(item['id'])
This will produce output like:
Total results: 4432
https://id.rijksmuseum.nl/200100988
https://id.rijksmuseum.nl/200105887
// ... more results ...
Retrieving all results
To retrieve all results across multiple pages, follow the next field until it is no longer present.
The example below retrieves all results across multiple pages, printing the number of items per page and the total number of items at the end.
import requests
# Define the search endpoint and parameters
url = "https://data.rijksmuseum.nl/search/collection"
params = {
"imageAvailable": "true",
"type": "painting",
"material": "oil paint"
}
all_items = []
page = 1
# Continue fetching until no next page is returned
while url:
response = requests.get(url, params=params)
data = response.json()
# Add the results to the list and print the page number
all_items.extend(data['orderedItems'])
print(f"Page {page}: {len(data['orderedItems'])} items")
page += 1
# Get the next page URL if available
next_page = data.get('next')
url = next_page['id'] if next_page else None
params = {} # Clear params: next URL already includes pageToken
print(f"\nRetrieved {len(all_items)} items in total")
This will produce output like:
Page 1: 100 items
Page 2: 100 items
...
Page 44: 100 items
Page 45: 32 items
Retrieved 4432 items in total
Resolving identifiers
Once you have a list of identifiers, you can resolve each one to retrieve full object metadata. The example below uses the la-framed profile to retrieve records in Linked Art format, and prints the full record for the first 5 results.
import requests
# Resolve a single identifier by requesting its URI with a profile parameter
def resolve_identifier(uri, profile="la-framed"):
response = requests.get(f"{uri}?_profile={profile}")
return response.json()
# Define the search endpoint and parameters
url = "https://data.rijksmuseum.nl/search/collection"
params = {
"imageAvailable": "true",
"type": "painting",
"material": "oil paint"
}
# Fetch the first page of results
response = requests.get(url, params=params)
data = response.json()
# Resolve the first 5 identifiers and print the result
for item in data['orderedItems'][:5]:
record = resolve_identifier(item['id'])
print(record)
This prints the full Linked Art record for each identifier. In the next step, we extract specific fields from this response.
Note: each identifier requires a separate request. For large result sets, this can significantly impact performance.
Extracting fields from the response
Rather than printing the full record, this example extracts specific fields — object number, title, creator, and identifier — and prints them in a readable format for the first 5 results.
import requests
def resolve_identifier(uri, profile="la-framed"):
response = requests.get(f"{uri}?_profile={profile}")
return response.json()
def extract_fields(record):
# Extract object number
object_number = None
for item in record.get('identified_by', []):
if item.get('type') == 'Identifier':
for classification in item.get('classified_as', []):
if classification.get('id') == 'https://id.rijksmuseum.nl/22015218':
object_number = item.get('content')
break
# Extract title
title = None
for item in record.get('identified_by', []):
if item.get('type') == 'Name':
for classification in item.get('classified_as', []):
if classification.get('id') == 'http://vocab.getty.edu/aat/300417200':
title = item.get('content')
break
# Extract creator name
creator = None
for part in record.get('produced_by', {}).get('part', []):
for actor in part.get('carried_out_by', []):
for notation in actor.get('notation', []):
if notation.get('@language') == 'en':
creator = notation.get('@value')
break
return object_number, title, creator
# Define the search endpoint and parameters
url = "https://data.rijksmuseum.nl/search/collection"
params = {
"imageAvailable": "true",
"type": "painting",
"material": "oil paint"
}
# Fetch the first page of results
response = requests.get(url, params=params)
data = response.json()
# Resolve the first 5 identifiers and extract key fields
for item in data['orderedItems'][:5]:
record = resolve_identifier(item['id'])
object_number, title, creator = extract_fields(record)
print(f"{object_number}")
print(f" Title: {title}")
print(f" Creator: {creator}")
print(f" Identifier: {item['id']}")
print()
This will produce output like:
SK-C-1535
Title: The Raampoortje in Amsterdam
Creator: Wouter Johannes van Troostwijk
Identifier: https://id.rijksmuseum.nl/200106078
SK-A-1453
Title: Willem Bilderdijk (1756-1831), dichter en geschiedschrijver
Creator: Charles Howard Hodges
Identifier: https://id.rijksmuseum.nl/200106079
// ... more results ...
Common pitfalls
- Parameters are combined using AND, not OR
- English terms are not always supported — Dutch terms have better coverage
- The
orderedItemsfield contains identifiers, not full object data - Retrieving many records requires resolving each identifier separately (N+1 requests), which can significantly impact performance
- Pagination must be handled using the
nextfield — there is no page number parameter
Summary
In this tutorial, you learned how to query the Rijksmuseum collection using the Search API. You explored the available parameters, how to interpret JSON responses, and how pagination works using pageToken.
You also learned how to retrieve all results programmatically, how to resolve Linked Open Data identifiers into full object records using the la-framed profile, and how to extract specific fields from the Linked Art response.