DocumentationAPI Reference
API ChangelogOpenAPI SpecStatus

Troubleshooting common issues

Speeding up initial load of the Persona integration

The Persona JS SDK functions by rendering an iframe that loads Persona's Hosted Flow Integration. Loading the assets needed can take a significant amount of time on low-quality connections. We provide several APIs and recommendations for improving initial load.

Preloading JavaScript assets

The SDK client provides a Client.preload() method that preloads the necessary assets into the browser's cache. Calling this method before calling new Client(...) can speed up initial load times. For more information, see Client Methods.

Eagerly instantiating Persona client

We generally recommend instantiating the Persona client as early as possible based on when the user signals intent to begin the flow, and calling open() on the client instance once the flow is ready to be displayed. This allows the Persona flow to begin loading in the background.

Opening widget onReady instead of onLoad

We provide two client callbacks related to initial load. onLoad fires when the iframe finishes loading, but the contents have not yet loaded, while onReady fires when the contents have loaded and are ready for user interaction. Opening the widget onReady and handling loading UI on your side can provide a smoother experience.

Ensure geographical routing is set if required

If your users are outside of the US, not specifying geographical routing will result in significantly increased latency. Use the routingCountry parameter to specify geographical routing if needed.

Refused to display '' in a frame because it set 'X-Frame-Options' to 'deny'

What this means

This error message is a result of a security feature that Persona offers when you integrate Persona using Embedded Flow.

Persona lets you specify, via an allowlist, which domains can load the embedded flow. You should specify only the domains where you embed your Persona flow. Potential attackers will then be blocked from embedding and loading your flow on their domain.

If you see this error, it means that the domain the embedded flow in being loaded on is not on the allowlist.

How to fix

If you see this error, go to the Embedded Flow integration page in the Persona Dashboard, and locate "Step 3 Configure allowed domains". Here, you'll see the Domain allowlist.

Ensure that:

  1. The domain from which you are trying to load the Embedded Flow (and where you're seeing the error message) is on the Domain allowlist.
  2. The domain in the Domain allowlist is correctly spelled and properly formatted. Note: a domain name should NOT include the http:// or https:// part of the URL.

If you are testing, please note:

  • localhost is enabled by default for Inquiries created in your Sandbox environment. localhost must be manually added to be usable for Production inquiries.

If you have a more complex setup, please note:

  • If your embedded flow is loaded on a webpage that is itself loaded as an iframe on another parent webpage, you must specify all parent origins by setting the frameAncestors option in the JS SDK. See Parameters for details.

High memory usage in browser

If you are seeing elevated memory usage, ensure you are not repeatedly calling new Persona.Client({ ... }) without cleaning up old clients with client.destroy(). Calling new Persona.Client({ ... }) multiple times without cleanup will load multiple instances of the Persona web flow via iframe, which will quickly consume available memory even if the iframes are not visible on the screen.

Server rendering

The Persona JS SDK requires client-side JavaScript and cannot be server rendered. If you are using a server rendered framework such as next.js or Remix, you will need to use the framework's client rendering escape hatch.


This error will manifest as ReferenceError: self is not defined when using next.js. To solve the problem, add the following snippet:

import dynamic from "next/dynamic";

export const PersonaInquiry = dynamic(
  () => import('persona').then((module) => module.Client),
  {ssr: false}


Dynamically import the embedded flow with

import { useEffect, useState } from "react";

export default function PersonaInquiry() {
  const [clientLoaded, setClientLoaded] = useState<boolean>(false);
  useEffect(() => {
    import('persona').then((module) => {
      // interact with module.Inquiry based on your integration
  }, []);

  // coordinate UI with clientLoaded

PDFs linked from the Inquiry flow cannot be loaded

Links that trigger PDFs to open in a popup require relaxing iframe sandbox restrictions via the allow-top-navigation-by-user-activation attribute. Note that relaxing sandbox restrictions has security implications and should be done with care.

Note that if you are testing your integration with an iframe-based tool such as JSFiddle, Codepen, or CodeSandbox, you may still see issues. This is because the Persona iframe is nested within the tool's own iframe, which has its own set of sandbox attributes. To properly test, use a local HTML file.

For more information, see iframe sandbox attributes.

I am running into issues when testing locally

If testing locally, ensure your webpage is served by a local web server instead of being opened as a static file. This is due to the origin for local files (file://) not being a valid origin for window.postMessage(), which the Persona flow uses to communicate with your code.

For example:

python -m http.server
open http://localhost:8000/your_html_file.html