Securely install the JavaScript SDK
Contents
The JavaScript SDK runs with the same access to your page as your own application code. Use version controls, Subresource Integrity (SRI), Content Security Policy (CSP), and nonces to control how you load it. These controls protect different boundaries; none makes untrusted code safe to run.
Pin and update SDK versions
If you need to review SDK changes before deployment, follow snippet versioning for CDN installations or the package-manager lockfile guidance for npm installations. Use an exact dependency version, commit the lockfile, and enforce frozen installs in CI.
Version pins and versioned feature scripts select releases; they don't verify the bytes returned by a CDN or proxy. The token-specific /array/<token>/config.js script isn't pinned by strict_script_versioning.
Review and deploy updates regularly so pins don't prevent security fixes from reaching your users. See keeping SDKs current.
Use Subresource Integrity with a pinned script
Subresource Integrity (SRI) enables the browser to check a downloaded script against an expected cryptographic hash before executing it. Use it with an exact-version URL, not a moving URL such as /static/array.js or /static/1/array.js.
Generate and review the hash
Download the exact asset you intend to deploy and calculate its SHA-384 digest. Version 1.444.0 below is an example; choose a release you have reviewed.
Use your actual regional asset host or reverse-proxy URL. Review the downloaded artifact through your normal dependency approval process, then store the expected hash in your application code. Calculating a hash from a compromised download doesn't establish that the code is trustworthy. Don't fetch the expected hash dynamically from the same server at page load.
Add the hash to the SDK script
In the HTML snippet, replace the p.src assignment with these comma-separated assignments, before the script is inserted into the DOM:
Replace <SHA384_BASE64_DIGEST> with the digest from the previous step, and keep the rest of the snippet unchanged. The URL must serve the exact bytes you hashed. Cross-origin SRI requires a CORS response header such as Access-Control-Allow-Origin: *; PostHog's asset hosts provide this. Preserve it if you serve assets through a cross-origin proxy.
Adding integrity to the outer inline <script> that contains the snippet doesn't protect the SDK it downloads. Set it on the generated p script element as shown above. When upgrading, update the version and hash together. If the hash doesn't match, the browser blocks execution; don't retry without integrity to work around the error.
Understand the coverage
SRI protects only the resource carrying the hash. Hashing array.js doesn't protect additional scripts it loads, including the recorder, surveys, toolbar, or config.js.
The prepare_external_dependency_script hook can set integrity on SDK-created dependency script elements when you maintain reviewed hashes for their exact URLs. It doesn't protect the initial array.js download or guarantee coverage of scripts created by other code. Don't apply one hash to every dependency, and don't use a fixed release hash for mutable project configuration.
If your requirement is to avoid runtime executable downloads altogether, use the bundled approach below instead of treating SRI on the initial script as complete coverage.
Configure Content Security Policy
CSP limits which resources the browser can load and which scripts it can execute. Follow the CSP directives guide for SDK scripts, API connections, workers, and optional toolbar resources.
Keep script-src and connect-src separate in your review: permitting event ingestion doesn't require permitting remote JavaScript. Bundling the SDK doesn't remove the need to permit its API requests. Test the features you enable before enforcing your policy, and use browser console reports to find blocked resources rather than broadly adding unsafe-inline or unsafe-eval.
Use CSP tracking to test your policy in report-only mode before enforcement and monitor violations after deployment.
A reverse proxy changes where requests go. It doesn't verify script contents or reduce the privileges of code running on your page.
Use nonces for authorized scripts and styles
Follow supporting nonce directives for SDK configuration. Generate an unpredictable nonce for each HTML response, and authorize the initial installation code as well as SDK-created elements.
Nonces authorize execution; they don't verify script contents or replace SRI.
Bundle the SDK without external scripts
To avoid runtime executable downloads, install the SDK from npm with a package manager and follow bundling extensions for the no-external import options and feature trade-offs. Installing from npm with the default posthog-js import doesn't prevent dependency downloads.
Set disable_external_dependency_loading: true at the first initialization of every SDK instance. This blocks the standard SDK script loader, including executable config.js. Without preloaded configuration, the SDK requests project configuration as JSON instead. Configuration, flags, and events still use the network. See the SDK configuration reference for available controls.
Don't combine this setup with the snippet, tag-manager installations, or another permissively configured SDK copy. No-external builds don't remove a shared loader or renderer already registered by another bundle.
Preventing script downloads doesn't sanitize remote HTML or disable bundled renderers. Review remotely configured UI separately. This setup doesn't isolate the SDK from your page or protect against a compromised package or build pipeline.
Review data access and verify your installation
Use only your public project token in browser code, never a personal API key. Client-side feature flags aren't authorization checks; enforce access control on your server.
Review data collection and consent and session replay masking separately. Capture opt-out settings aren't a guarantee of no network requests or script downloads.
Before deployment and after each upgrade:
- Use a clean browser profile to check the Network panel during initialization, event capture, feature flag evaluation, and optional features.
- Check for duplicate SDK installations, unexpected executable downloads, CSP violations, and integrity failures.
- For the no-external setup, verify that JSON configuration, flags, and events work without vendor script downloads. Test without CSP first, then with CSP, so blocked requests don't hide unwanted loading attempts.
- For SRI, test that an incorrect hash blocks execution and that the correct hash loads the SDK. Check any proxy or CDN transformations that could change the bytes.





