By default, any website can call your instance from the browser. The response always carries Access-Control-Allow-Origin: *, which is PocketBase’s default too.
To allow only your own sites, add a secret named PH_CORS_ORIGINS with a comma-separated list of origins:
https://app.example.com, https://admin.example.com, http://localhost:5173 It takes effect within a few seconds. You don’t need to restart the instance. Files Cloudflare has already cached update when they expire (see Cached files below).
Each entry is an origin: a scheme, a host, and an optional port, such as https://app.example.com or http://localhost:5173. Leave out any path and trailing slash, because the browser’s Origin header never has one.
The matching works the same as PocketBase’s --origins flag:
* on its own allows every origin.* inside an entry matches any characters. https://*.example.com allows https://app.example.com but not https://example.com.? matches a single character.Spaces around the commas are ignored. Nothing else is checked, so an entry with a typo simply never matches.
Access-Control-Allow-Origin: <that origin>.PocketHost applies this at the edge for every response from your instance: the API, realtime, files, pb_public and your own hook routes. It also covers the edge’s own responses, such as rate limits and “instance is powered off”. Preflight (OPTIONS) requests are answered at the edge, so they don’t wake a sleeping instance.
When PH_CORS_ORIGINS is set, it replaces any CORS headers your own hooks send.
CORS only affects browsers. It doesn’t stop scripts, servers or apps from calling your API. Use API rules for access control.
Cloudflare caches some files, such as images in pb_public and files served from /api/files, separately for each origin, so CORS works for cached files too. If you change PH_CORS_ORIGINS, copies Cloudflare has already cached keep their old CORS header until they expire.
Delete the secret. Within a few seconds every origin is allowed again, apart from files Cloudflare has already cached.
Self-hosted PocketBase does the same thing with its --origins flag:
./pocketbase serve --origins=https://app.example.com,https://admin.example.com