Build Chrome extensions quicker with a TypeScript boilerplate project
Download

How to use Web Accessible Resources in Chrome Extensions

ExtensionNinja | 2/11/2023

You are working on a content script that shows your custom UI on a website and you want to display your extension logo or use your brand font. How do you achieve this? One way is to host these resources on your website or CDN and hardcode URLs in your content script code.

But you may be in the situation where you don’t have a website or want to manage, support and pay for a complex flow of deploying resources somewhere on the internet. In this article, we will explore an alternative way to supply web resources to your content script that is fully self-contained to your extension code and deployment.

Web_accessible_resources to the rescue

The web accessible resources feature allows you expose certain files from your extension package to any website or extension and make them referenceable from content scripts.

manifest.json

{
    "web_accessible_resources": [ 
        { 
            "resources": ["icons/icon128.png"], 
            "matches": ["https://www.extension.ninja/*"], 
            "use_dynamic_url": true 
        },
        { 
            "resources": ["icons/*.png"], 
            "matches": ["*://*/*"], 
        },
        { 
            "resources": ["icons/*"], 
            "extension_ids": ["mckfpgomanpbigaehgjiencpkjgphhmi"], 
        },
    ]
}

More in official extension docs: Chrome Extensions Manifest: web_accessible_resources.

Programmatically referencing resources

Resource URL can be dynamically generated in content script code by using chrome.runtime.getURL method.

You could use it like this:

    image.src = chrome.runtime.getURL(“images/image.png”);

Referencing extension resources in static files

Let’s say you injected a CSS file to website content and want to reference a custom font packaged in your extension. You can't run chrome.runtime.getURL in CSS. But you can use a little bit of extension magic __MSG_@@extension_id__.

__MSG_@@extension_id__ is a special string that gets replaced with extension id in static files at runtime.

.logo {
    background: url('chrome-extension://__MSG_@@extension_id__/icons/icon128.png');
}

Referencing resources in extension pages

All extension resources are by default accessible to extension internal pages. You don’t have to include resources in web_accessible_resources for this.

Security and privacy considerations when using Web Accessible Resources

By exposing extension resources to other websites, especially without domain restrictions, you are making your extension easier to fingerprint. Websites will be able to detect that visitors are using your extension and block visitors or uniquely identify them as users of your extension.

Fingerprinting is possible because resource URLs have your unique extension ID. This can be mitigated by setting use_dynamic_url: true. This changes resource URLs to use unique session ID, which changes with each browser restart or extension reload. The downside of dynamics URL is that it can only be generated by your extension code. Other extensions and websites will not be able to reference the resource by a consistent URL. You could use multiple web accessible resource entries to design a policy that fits your scenario.

In general, you should follow the principle of least privilege access when declaring web accessible resources.

Common exceptions and gotchas

Check browser console for exceptions. Chrome has quite descriptive error messages and it will help you to diagnose the problem. Usually, you either have an error in URL of the resource or website does not match query in the manifest definition.

Example error message: Denying load of chrome-extension://.... Resources must be listed in the web_accessible_resources manifest key in order to be loaded by pages outside the extension.

Also be aware that extension id during development and release may not be the same. This will break your URLs in production. If you want to rely on hard-coded URLs then check out the guide how to make extension ids consistent in development and release.

Lastly, you cannot use the web accessible resources feature to expose CSS or JS files. You need to use content injection API for CSS and JS files.

Don't miss latest Chrome extension developer news

Join Newsletter