Common questions about security, privacy, and how the proxy works.
No. The proxy URLs (/apps/proxy/...) only exist on your Shopify storefront. When a request comes in, Shopify’s App Proxy gateway signs it with a cryptographic HMAC signature using your app’s secret key. The Cloudflare Worker verifies this signature before processing any request.
If someone tries to call the Worker URL directly (bypassing Shopify), the request has no valid signature and is immediately rejected with a 401 Unauthorized. There is no way to forge this signature without your app’s secret.
A visitor browsing your store (or using the browser console) can call your configured proxy routes - that’s by design, since your theme code needs to call them too. However, they can only hit the exact routes you configured with the exact target URLs and methods you defined. They cannot change the destination, inject different headers, or access other merchants’ data.
All proxy routes are also rate-limited to 120 requests per minute per route, and monthly usage is capped by your plan limit, so even automated abuse is bounded.
No. API keys and secret headers are stored in Cloudflare KV and injected server-side by the Worker. They never appear in the HTML source, JavaScript bundles, network responses, or browser DevTools. The storefront visitor only sees the final API response data - never the credentials used to fetch it.
This is the entire purpose of the app: keeping your API keys completely hidden from client-side code.
Your API keys stay hidden regardless of the HTTP method. However, for routes that write or modify data (POST, PUT, PATCH), be aware that any visitor on your store could potentially call that endpoint from the browser console. To mitigate this:
For highly sensitive write operations (payments, account creation), a dedicated backend with full user authentication is recommended over any client-side proxy.
The nonce system prevents replay attacks and console-scripted spam on POST routes. When enabled, the frontend must get a single-use token before submitting data:
GET /apps/proxy/{route}?_action=nonce to receive a nonce, timestamp, and cryptographic signature._nonce, _nonce_ts, and _nonce_sig in the POST body alongside the form data.This means each POST needs its own unique GET request first. Console-based spam scripts are slowed to one request at a time, and replaying a captured request always fails because the nonce is single-use.
A body template lets you define the exact JSON structure that gets sent to the upstream API. Instead of the frontend controlling the full payload, it only sends simple field values (like name and email). The Worker merges these into your template server-side.
Benefits:
{{_customer_id}} and {{_timestamp}} are injected server-side - the frontend can’t fake them.