Content Security Policy and ingestion domains

Last updated:

|Edit this page

Using Content Security Policies

NOTE: This only applies to PostHog Cloud.

As described on MDN: Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft, to site defacement, to malware distribution.

If you choose to use a CSP it is important to ensure that PostHog domains are permitted. PostHog is a distributed Cloud service and as such can have different domains that change over time but will always be served from the root domain posthog.com. As such you should add *.posthog.com to your CSP directive.

Domains used by PostHog clients

WARNING: Adding more specific domains is not recommended as we may change target subdomains over time. If you do specify a non-wildcard domain, we cannot guarantee that it will continue to work in the future.

Our client SDKs (where appropriate) will take care of selecting the correct domain. Typically you do not need to be aware of these domains. For example when you specify api_host: "https://app.posthog.com" the SDK will recognize this as a US configuration and make the correct calls to us.i.posthog.com or us-assets.i.posthog.com accordingly.

DomainUsage
us.i.posthog.comUS ingestion endpoint for client SDK API calls
us-assets.i.posthog.comUS CDN for client SDK assets (such as array.js)
eu.i.posthog.comEU ingestion endpoint for client SDK API calls
eu-assets.i.posthog.comEU CDN for client SDK assets (such as array.js)
eu.posthog.comEU PostHog app domain (used by the Toolbar) and also legacy ingestion
us.posthog.comUS PostHog app domain (used by the Toolbar)
app.posthog.comLegacy ingestion endpoint

Questions?

  • Art
    11 days ago

    Syntax error in nonce code

    As is, the code says:

    posthog.init('phc_6iWc02QPj39avNptuPSS0il7XQtdGkvCMXRiAewcT6m', {
    prepare_external_dependency_script = (script) => {
    script.nonce = '<your-nonce-value>'
    return script
    },
    prepare_external_dependency_stylesheet = (stylesheet) => {
    stylesheet.nonce = '<your-nonce-value>'
    return stylesheet
    }
    })

    But, we're passing an object to init. So prepare_* are keys, not variables. The = should be ::

    posthog.init('phc_6iWc02QPj39avNptuPSS0il7XQtdGkvCMXRiAewcT6m', {
    prepare_external_dependency_script: (script) => {
    script.nonce = '<your-nonce-value>'
    return script
    },
    prepare_external_dependency_stylesheet: (stylesheet) => {
    stylesheet.nonce = '<your-nonce-value>'
    return stylesheet
    }
    })
  • Denis
    3 months ago

    How to set nonce for recorder and surveys scripts

    In a React app using the posthog-js package, how to set the nonce attribute for the recorder.js and surveys.js scripts that are fetched dynamically?

    • Ben
      3 months agoSolution

      Not currently supported but got a PR up to add support here!

  • Diene
    4 months ago

    Challenges Configuring Content Security Policy

    I'm encountering some difficulties configuring PostHog in my application due to Content Security Policy (CSP) restrictions. I hope someone can provide some guidance or suggestions to help resolve these issues!

    Context: I'm trying to implement PostHog for event tracking in my application, but the CSP settings are causing conflicts, resulting in errors related to the use of inline scripts, inline styles, and restrictions on external fonts.

    Is there a CSP configuration recommended by the PostHog community that can help minimize these issues without compromising security?

    Here’s my current implementation:

    • Max
      4 months ago

      For PostHog Cloud, you need to ensure your CSP includes all the required domains. These specific domains are:

      • us.i.posthog.com for US API calls(1)
      • us-assets.i.posthog.com for US client assets(1)
      • eu.i.posthog.com for EU API calls(1)
      • eu-assets.i.posthog.com for EU client assets(1)
      • eu.posthog.com for EU app and legacy ingestion(1)
      • us.posthog.com for US app domain(1)
      • app.posthog.com for legacy ingestion(1)

      If you have session recordings enabled, you'll need additional CSP configurations as PostHog will fetch a recorder.js script. This requires proper CSP directives for default-src, script-src, script-src-elem, or connect-src(2).

      For surveys functionality, PostHog needs to fetch survey.js, which also requires appropriate CSP permissions(3).

      The recommended approach is to use *.posthog.com in your CSP directive rather than specific domains, as target subdomains may change over time(1).

      Check your browser's developer console for specific CSP violation errors to help identify which domains or directives are causing issues(3).

  • Thomas
    5 months ago

    What CSP directives need to be set?

    In my CSP header, which directives do I need to include *.posthog.com to? Just connect-src and script-src, or do I need to add others?

Was this page useful?

Next article

Product analytics for browser extensions

Do you have a Firefox or Chrome browser plugin with a user interface and want to understand how it's being used? PostHog is the perfect way to do just that. Setup for Firefox & Chrome plugins Installing PostHog inside your plugin Open the HTML file used in your default_popup and add the PostHog array.js script. To do this you'll need to either: Copy the latest version of array.js from PostHog's static assets and import it locally using <script src="array.js" /> before the </head> tag…

Read next article