Home » Solution: CORS Error When Consuming External APIs from Shopify Templates
Web & Code

Solution: CORS Error When Consuming External APIs from Shopify Templates

✨ Quick Answer

When sending fetch() or axios requests from a Shopify theme storefront script to an external backend, the browser halts execution with: Access to fetch at 'https://my-api.com' from origin 'https://my-store.myshopify.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present.

Quick Diagnostics

Cause
fetch() request from Liquid theme to external backend missing Access-Control-Allow-Origin
Solution
Add proper CORS response headers on external server or route via Shopify App Proxy
Cause
Blocked preflight OPTIONS requests or HTTP mixed content on HTTPS storefront
Solution
Ensure endpoints support HTTPS and return HTTP 200/204 to OPTIONS requests

When sending fetch() or axios requests from a Shopify theme storefront script to an external backend, the browser halts execution with: Access to fetch at 'https://my-api.com' from origin 'https://my-store.myshopify.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present.

Step-by-Step Solution

Step 1: Configure CORS Headers on External Backend

Allow the Shopify storefront domain to communicate with your backend. In Node.js / Express:

JAVASCRIPT
import cors from 'cors';
import express from 'express';
const app = express();

const allowedOrigins = [
  'https://my-store.myshopify.com',
  'https://www.my-store.com'
];

app.use(cors({
  origin: function(origin, callback) {
    if (!origin || allowedOrigins.indexOf(origin) !== -1) {
      callback(null, true);
    } else {
      callback(new Error('Blocked by CORS'));
    }
  },
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true
}));

Shopify Application Proxies tunnel requests through your store domain, completely avoiding CORS restrictions:

  1. 1

    Step 1

    In Shopify Partner Dashboard > App Setup > App Proxy, define a proxy path such as apps/my-proxy.
  2. 2

    Step 2

    Point the destination to your server URL: https://my-api.com/api/.
  3. 3

    Step 3

    Execute client-side storefront requests against the same-origin URL:
JAVASCRIPT
// Fetch directly from same origin - no CORS headers needed
fetch('/apps/my-proxy/get-data', {
  method: 'GET',
  headers: { 'Content-Type': 'application/json' }
})
.then(res => res.json())
.then(data => console.log('Storefront Data:', data));

Step 3: Support Preflight OPTIONS Requests

Ensure your backend returns HTTP 200 or 204 status codes for preflight OPTIONS requests when Content-Type: application/json is utilized.

❓ Frequently Asked Questions (FAQ)

Can CORS headers be set in Liquid files?

No. Liquid is a server-side template engine that produces HTML. CORS validation happens on the client browser when dispatching AJAX requests to external hosts.

Why is App Proxy superior for private store data?

Shopify signs all App Proxy requests using HMAC-SHA256 headers, allowing your backend to verify that requests originate from an authorized store session.

Prevention Advice

Recommended security practices:

  • Do not use wildcard wildcard (*) with credentials: Wildcard origin matching disables cookies/authorization tokens and leaves endpoints open to third-party scraping.
  • Enforce HTTPS everywhere: Shopify storefronts run strictly over HTTPS. Any HTTP resource request will be blocked immediately as Mixed Content.
Author • Web Designer & App Creator

Rodolfo Castro

Web designer, app developer, and founder of SoporteCero. Specializing in UI/UX architecture, digital products, and modern web environments. Every tutorial and guide on SoporteCero is thoroughly tested and verified in our technical lab to ensure reliable, up-to-date solutions.