CORS for registries
If you want browser-based clients (including the validator) to be able to read your registry, you need to enable CORS.
Why CORS matters
Native apps fetch HTTP responses directly and ignore browser security headers, so a registry without CORS works fine for them. Browsers, on the other hand, refuse to expose responses from another origin to JavaScript unless the server opts in by sending the Access-Control-Allow-Origin header.
That means a registry without CORS is invisible to:
- This site's validator (it can't read your responses, so it can't tell you if your registry is compliant)
- Any in-browser comic reader or directory built on the standard
- Browser extensions and installable web apps
If you want your registry to be able to be consumed by browser-based clients alongside native apps, configure CORS.
What to send
The minimum: respond to requests under /openwebcomics/api/v1/ with
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
The Open Web Comics API only uses GET, sends no credentials, and does not need custom request headers. The simplest correct configuration is to allow all origins (*) for the API path. If you want to restrict to a known set of clients, send a specific origin instead — but in that case you must vary by request origin and respond with the matching value (a wildcard plus a specific origin is not valid).
Example configurations
Netlify (_headers)
Add a file called _headers at the root of the deployed site:
/openwebcomics/api/v1/*
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Cloudflare Pages (_headers)
Same syntax as Netlify — drop a _headers file at the root.
Nginx
location /openwebcomics/api/v1/ {
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
if ($request_method = OPTIONS) {
return 204;
}
}
Apache (.htaccess)
<LocationMatch "^/openwebcomics/api/v1/">
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, OPTIONS"
</LocationMatch>
Express / Node.js
import cors from "cors"
app.use("/openwebcomics/api/v1", cors({ origin: "*", methods: ["GET", "OPTIONS"] }))
Cloudflare Workers / generic edge function
const headers = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, OPTIONS",
}
return new Response(body, { headers: { ...headers, "Content-Type": "application/json" } })
S3 + CloudFront
Set a CORS configuration on the bucket that allows GET from any origin, then attach a Response Headers Policy to the CloudFront distribution that injects Access-Control-Allow-Origin: * on responses.
Testing
The fastest sanity check:
curl -sI -H "Origin: https://example.test" \
https://your-registry.example/openwebcomics/api/v1/info \
| grep -i access-control
You should see access-control-allow-origin: * (or your specific origin) in the response headers. If nothing appears, the header is not being sent.
Once that's working, the validator on this site will be able to crawl your registry and report any spec compliance issues.
Things to avoid
- Don't send
Access-Control-Allow-Credentials: true. The API doesn't use credentials, and combining it withAllow-Origin: *is invalid. - Don't echo the request
Originback blindly without an allowlist if you also intend to support credentials elsewhere on the same host — that's a common cross-site request forgery pitfall. - Don't restrict
Allow-Originto a single hardcoded origin if you actually want any browser to be able to read it. Use*.