Configure CORS for External SVG Symbols

Loading external SVG sprites and symbols across different domains using the <use> element often fails due to browser Same-Origin Policy restrictions. To permit external SVG symbol loading, the hosting server must deliver the SVG files with appropriate Cross-Origin Resource Sharing (CORS) headers and the correct MIME type. This guide details the exact HTTP headers required and demonstrates how to configure them across popular web servers and cloud platforms.

Required HTTP Response Headers

To allow cross-origin fetching of SVG assets, the server hosting the .svg files must include the following headers in its response:


Web Server Configurations

1. Nginx Configuration

In your Nginx server block or configuration file (nginx.conf), add a location directive matching .svg files to append the CORS headers:

location ~* \.svg$ {
    # Specify allowed origin or use wildcard
    add_header Access-Control-Allow-Origin "*";
    add_header Access-Control-Allow-Methods "GET, OPTIONS";
    add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";

    # Ensure correct MIME type
    types {
        image/svg+xml svg;
    }

    # Optional: Cache control for static assets
    expires 30d;
    add_header Cache-Control "public, no-transform";
}

Reload Nginx after saving changes:

sudo nginx -s reload

2. Apache Configuration

Ensure that Apache’s mod_headers module is enabled (sudo a2enmod headers). Then, add the configuration to your .htaccess file or inside the <VirtualHost> / <Directory> block:

<IfModule mod_headers.c>
    <FilesMatch "\.(svg|svgz)$">
        Header set Access-Control-Allow-Origin "*"
        Header set Access-Control-Allow-Methods "GET, OPTIONS"
        Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"
    </FilesMatch>
</IfModule>

# Ensure correct MIME type
AddType image/svg+xml .svg .svgz

Reload Apache to apply changes:

sudo systemctl reload apache2

3. Caddy Server

If you use Caddy, use the header directive inside your Caddyfile:

example.com {
    @svg path *.svg
    header @svg {
        Access-Control-Allow-Origin "*"
        Access-Control-Allow-Methods "GET, OPTIONS"
    }
}

4. Amazon Web Services (AWS) S3

If your SVG assets are hosted on an Amazon S3 bucket, configure the bucket’s CORS permissions:

  1. Open the AWS S3 Console and select your bucket.
  2. Navigate to the Permissions tab and scroll to Cross-origin resource sharing (CORS).
  3. Click Edit and insert the following JSON configuration:
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]

Note: If using AWS CloudFront in front of S3, ensure your CloudFront distribution is configured to forward the Origin header to the S3 origin and cache based on it.


5. Node.js (Express)

For an Express-based static server, apply headers specifically to SVG requests using express.static:

const express = require('express');
const app = express();

app.use(express.static('public', {
    setHeaders: (res, path) => {
        if (path.endsWith('.svg')) {
            res.set('Access-Control-Allow-Origin', '*');
            res.set('Access-Control-Allow-Methods', 'GET, OPTIONS');
            res.set('Content-Type', 'image/svg+xml');
        }
    }
}));

Verifying the CORS Configuration

To verify that your server is properly returning the headers, test the SVG URL using curl from the command line:

curl -I -H "Origin: https://example.com" https://cdn.example.com/icons/sprite.svg

Look for the following lines in the output:

HTTP/1.1 200 OK
Content-Type: image/svg+xml
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS

Once these headers are present, modern browsers will load and render external SVG symbols via <svg><use href="https://cdn.example.com/sprite.svg#icon-name"></use></svg> without cross-origin security errors.