Open Source Projects — entry 002 of 8
Creative Commons Catalog
Creative Commons's search catalog was handed off to WordPress.org and relaunched as Openverse; the old `api.creativecommons.engineering` host now 301-redirects to the current `api.openverse.org`. A live unauthenticated GET against `api.openverse.org/v1/images/` returned a 200 JSON result set with `Access-Control-Allow-Origin: *`, confirming keyless anonymous search still works today (rate-limited to 200 requests/day per IP), with an optional `/v1/auth_tokens/register/` OAuth2 client-registration endpoint (confirmed live, returning a 400 validation error rather than 404) for higher limits. The catalog itself and every indexed work are free to use under their respective open licenses.
Openverse (the relaunched Creative Commons Catalog) exposes openly-licensed media search over a plain REST/JSON API. A live GET to /images/?q=bicycle&page_size=1 returned a 200 JSON body with result_count, page_count, page_size, page, and a results array of full media records (license, creator, attribution text, thumbnail/detail/related URLs), and access-control-allow-origin: * confirmed anonymous cross-origin access — both reconfirmed by this run's own probe.
GreatAPIs Score
Auth quickstart
- No API key or signup required for anonymous search — every probe in this file returned real results with no auth header sent at all, subject to the anonymous rate limits below.
- Anonymous requests are rate-limited (see the
rateLimitgotcha below); registering an OAuth2 application at/v1/auth_tokens/register/gets a higher, per-application limit instead of the shared anonymous one — that endpoint live-returns a 400 validation error (not 404) when called without the required fields, confirming it's a real, reachable route rather than documentation-only.
Your key is stored only in this browser (localStorage) and sent directly to the API — never to greatapis.
Endpoints
auth3
Openverse provides free and open access to the Openverse API to anonymous and registered users. [Refer to the API documentation site for information on how to register](https://api.openverse.org/v1/#tag/auth). All Openverse API users are subject to rate limits and restrictions on how much of Openverse's dataset can be accessed through the API. [Individuals should contact Openverse to request expanded access to the API](https://github.com/WordPress/openverse#keep-in-touch). Requests are considered on a case-by-case basis and are subject to evaluation in light of [Openverse's Terms of Service](https://docs.openverse.org/terms_of_service.html). Escalated access may be revoked at any time. To authenticate yourself, you must sign up for an API key using the `register` endpoint and then get an access token using the `token` endpoint. Read on to know about these endpoints. In subsequent requests, include your access token as a bearer token in the `Authorization` header. ``` Authorization: Bearer <access_token> ``` ### Rate limits Openverse endpoints are rate limited. Anonymous requests should be sufficient for most users. Indeed, https://openverse.org itself operates using anonymous requests from the browser. Registered users are automatically granted slightly higher limits. Further increases to rate limits are available upon request (see above). Every Openverse API response that was subject to rate-limits includes headers outlining the permitted and available usage. Exceeding the limit will result in '429: Too Many Requests' responses. ### Pagination Openverse's dataset is valuable, and the [Terms of Service](https://docs.openverse.org/terms_of_service.html) disallow scraping under all circumstances. As such, pagination for anonymous users is limited, accommodating only the typical usage on https://openverse.org. Pagination is limited in terms of the size of individual pages and the total number of works visible for a query (pagination depth). Authenticated users are subject to the same limit of total works available for a query, but may request larger individual pages. Increases to pagination limits on page size and total depth are available upon request (see above).
POST/v1/auth_tokens/register/
application/json — OAuth2Registration (required)
| Status | Description | Schema |
|---|---|---|
201 | Created | OAuth2Application |
400 | Bad Request | ValidationError |
401 | Unauthorized | — |
429 | Too Many Requests | APIException |
POST/v1/auth_tokens/token/
application/x-www-form-urlencoded — OAuth2TokenRequest (required)
| Status | Description | Schema |
|---|---|---|
200 | OK | OAuth2Token |
400 | Bad Request | APIException |
401 | Unauthorized | NotAuthenticated |
GET/v1/rate_limit/
| Status | Description | Schema |
|---|---|---|
200 | OK | OAuth2KeyInfo |
401 | Unauthorized | NotAuthenticated |
429 | Too Many Requests | APIException |
500 | Internal Server Error | APIException |
audio8
These are endpoints pertaining to audio files.
GET/v1/audio/
| Name | In | Required | Type |
|---|---|---|---|
page | query | no | integer |
page_size | query | no | integer |
q | query | no | string |
source | query | no | string |
excluded_source | query | no | string |
tags | query | no | string |
title | query | no | string |
creator | query | no | string |
unstable__collection | query | no | string |
unstable__tag | query | no | string |
license | query | no | string |
license_type | query | no | string |
filter_dead | query | no | boolean |
extension | query | no | string |
mature | query | no | boolean |
unstable__sort_by | query | no | string |
unstable__sort_dir | query | no | string |
unstable__authority | query | no | boolean |
unstable__authority_boost | query | no | number |
unstable__include_sensitive_results | query | no | boolean |
category | query | no | string |
length | query | no | string |
peaks | query | no | boolean |
| Status | Description | Schema |
|---|---|---|
200 | OK | PaginatedAudioList |
400 | Bad Request | ValidationError |
401 | Unauthorized | NotAuthenticated |
GET/v1/audio/stats/
| Status | Description | Schema |
|---|---|---|
200 | OK | — |
401 | Unauthorized | AuthenticationFailed |
GET/v1/audio/{identifier}/
| Name | In | Required | Type |
|---|---|---|---|
identifier | path | yes | string |
| Status | Description | Schema |
|---|---|---|
200 | OK | Audio |
401 | Unauthorized | AuthenticationFailed |
404 | Not Found | NotFound |
GET/v1/audio/{identifier}/related/
| Name | In | Required | Type |
|---|---|---|---|
identifier | path | yes | string |
| Status | Description | Schema |
|---|---|---|
200 | OK | PaginatedAudioList |
401 | Unauthorized | AuthenticationFailed |
404 | Not Found | NotFound |
POST/v1/audio/{identifier}/report/
| Name | In | Required | Type |
|---|---|---|---|
identifier | path | yes | string |
application/json — AudioReportRequest (required)
| Status | Description | Schema |
|---|---|---|
201 | Created | AudioReportRequest |
400 | Bad Request | ValidationError |
401 | Unauthorized | AuthenticationFailed |
404 | Not Found | NotFound |
GET/v1/audio/{identifier}/thumb/
| Name | In | Required | Type |
|---|---|---|---|
identifier | path | yes | string |
full_size | query | no | boolean |
compressed | query | no | boolean |
| Status | Description | Schema |
|---|---|---|
200 | Thumbnail image | — |
401 | AuthenticationFailed | |
404 | NotFound |
GET/v1/audio/{identifier}/waveform/
| Name | In | Required | Type |
|---|---|---|---|
identifier | path | yes | string |
| Status | Description | Schema |
|---|---|---|
200 | OK | AudioWaveform |
401 | Unauthorized | AuthenticationFailed |
404 | Not Found | NotFound |
GET/v1/images/{identifier}/thumb/
| Name | In | Required | Type |
|---|---|---|---|
identifier | path | yes | string |
full_size | query | no | boolean |
compressed | query | no | boolean |
| Status | Description | Schema |
|---|---|---|
200 | Thumbnail image | — |
401 | AuthenticationFailed | |
404 | NotFound |
images6
These are endpoints pertaining to images.
GET/v1/images/
| Name | In | Required | Type |
|---|---|---|---|
page | query | no | integer |
page_size | query | no | integer |
q | query | no | string |
source | query | no | string |
excluded_source | query | no | string |
tags | query | no | string |
title | query | no | string |
creator | query | no | string |
unstable__collection | query | no | string |
unstable__tag | query | no | string |
license | query | no | string |
license_type | query | no | string |
filter_dead | query | no | boolean |
extension | query | no | string |
mature | query | no | boolean |
unstable__sort_by | query | no | string |
unstable__sort_dir | query | no | string |
unstable__authority | query | no | boolean |
unstable__authority_boost | query | no | number |
unstable__include_sensitive_results | query | no | boolean |
category | query | no | string |
aspect_ratio | query | no | string |
size | query | no | string |
| Status | Description | Schema |
|---|---|---|
200 | OK | PaginatedImageList |
400 | Bad Request | ValidationError |
401 | Unauthorized | NotAuthenticated |
GET/v1/images/oembed/
| Name | In | Required | Type |
|---|---|---|---|
url | query | yes | string |
| Status | Description | Schema |
|---|---|---|
200 | OK | Oembed |
400 | Bad Request | ValidationError |
401 | Unauthorized | AuthenticationFailed |
404 | Not Found | NotFound |
GET/v1/images/stats/
| Status | Description | Schema |
|---|---|---|
200 | OK | — |
401 | Unauthorized | AuthenticationFailed |
GET/v1/images/{identifier}/
| Name | In | Required | Type |
|---|---|---|---|
identifier | path | yes | string |
| Status | Description | Schema |
|---|---|---|
200 | OK | Image |
401 | Unauthorized | AuthenticationFailed |
404 | Not Found | NotFound |
GET/v1/images/{identifier}/related/
| Name | In | Required | Type |
|---|---|---|---|
identifier | path | yes | string |
| Status | Description | Schema |
|---|---|---|
200 | OK | PaginatedImageList |
401 | Unauthorized | AuthenticationFailed |
404 | Not Found | NotFound |
POST/v1/images/{identifier}/report/
| Name | In | Required | Type |
|---|---|---|---|
identifier | path | yes | string |
application/json — ImageReportRequest (required)
| Status | Description | Schema |
|---|---|---|
201 | Created | ImageReportRequest |
400 | Bad Request | ValidationError |
401 | Unauthorized | AuthenticationFailed |
404 | Not Found | NotFound |
Try it
Developer reference
https://api.openverse.org20 requests/min burst + 200 requests/day sustained for anonymous requests, confirmed live via the x-ratelimit-limit-anon_burst / x-ratelimit-limit-anon_sustained response headers
- GET/v1/images/
- GET/v1/audio/
Gotchas & limits
- Omitting the trailing slash on the collection path triggers a redirect, not a direct 200: a live GET to
/v1/images?q=bicycle&page_size=1(no trailing slash) returned HTTP 301 withlocation: /v1/images/?page_size=1&q=bicycle— note the query params are also reordered in the Location header — so a client that doesn't follow redirects gets nothing back. - An out-of-range
page_sizefails with HTTP 401, not 400: a live GET to/v1/images/?q=bicycle&page_size=999returnedHTTP 401 Unauthorizedwith body{"detail":"page_size may not exceed 20 for anonymous requests"}and awww-authenticate: Bearer realm="api"header — a genuinely surprising status code for what is really a parameter-validation error, not an auth failure. - An unknown image id 404s with a JSON error envelope: a live GET to
/v1/images/00000000-0000-0000-0000-000000000000/returnedHTTP 404with body{"detail":"No Image matches the given query."}. - The rate limit is live-measurable from response headers on every call: this run's probes consistently returned
x-ratelimit-limit-anon_burst: 20/minandx-ratelimit-limit-anon_sustained: 200/day, plus decrementingx-ratelimit-available-anon_burst/x-ratelimit-available-anon_sustainedcounters — read those before assuming a request budget.
Availability
Changelog
- gained rate limits
- gained an OpenAPI spec
- content changed
- content changed