Klarna

Checkout

Display Klarna at checkout with the JavaScript SDK, then get authorization for the purchase.
During the checkout, your customers can see Klarna as a payment option, select it, and go ahead with the purchase. Everything on this page happens on the client side using Klarna's JavaScript SDK. To enable it, complete three steps:
  1. 1.
    Set up Klarna's JavaScript SDK — add the SDK, initialize it, and place the widget container on your checkout page.
  2. 2.
    Display Klarna — make the load() call to show Klarna as a payment option.
  3. 3.
    Get authorization — make the authorize() call to get authorization for the purchase.

Set up Klarna's JavaScript SDK

Add the SDK to your checkout page, initialize it with your client_token, then add a container where the widget renders.

Add the SDK to your page

Add the SDK by including the following script in the body section of your checkout page.
MARKUP
1 2 3 4 5 6 7 8
<script> window.klarnaAsyncCallback = function () { // This is where you start calling Klarna's JS SDK functions // // Klarna.Payments.init({....}) }; </script> <script src="https://x.klarnacdn.net/kp/lib/v1/api.js" async></script>
A sample of Klarna's JavaScript SDK in the checkout page.
You do not need to install the JavaScript SDK beforehand. It's enough to include the previous script in the HTML file of your checkout page.

Configure your page for the SDK

If your site sets security headers, make sure they allow Klarna. These settings apply to every integration — whether you load Klarna at the top level or inside an iframe.
Content-Security-Policy. Allow Klarna's hosts. These directives extend your existing policy — if you use a default-src policy, make sure these hosts also appear in the corresponding directives. The img-src host lets the browser render the Klarna logo from the asset_urls on x.klarnacdn.net.
MARKUP
1 2 3 4
script-src https://x.klarnacdn.net https://js.klarna.com; connect-src https://*.klarna.com https://*.klarnaevt.com https://js.klarna.com https://x.klarnacdn.net; frame-src https://*.klarna.com https://x.klarnacdn.net; img-src https://x.klarnacdn.net;
Cross-Origin-Opener-Policy. If you set a Cross-Origin-Opener-Policy, use same-origin-allow-popups. Send it as an HTTP response header — browsers ignore Cross-Origin-Opener-Policy when it's set through a <meta> tag.
MARKUP
1
Cross-Origin-Opener-Policy: same-origin-allow-popups
Avoid Cross-Origin-Opener-Policy: same-origin. It severs the reference between your page and the Klarna pop-up that the flow uses to re-focus the pop-up and to drive the recovery backdrop. same-origin-allow-popups keeps that reference while preserving the same isolation. If you set this header through a security middleware (for example, Helmet), use same-origin-allow-popups, or run the policy in report-only mode while you migrate.

Load Klarna SDK

You can load the Klarna SDK integration in two ways: at the top level of your page (the first-party context) or inside an iframe. Load it at the top level whenever you can — this is Klarna's recommended approach, gives the most reliable customer experience, and keeps every Klarna feature available. Only use an iframe if your architecture requires it, and follow the iframe guidance closely.
Load Klarna SDK in the first-party context
Load the Klarna SDK integration directly in the top-level document of your checkout page. The first-party context avoids the browser restrictions that apply to framed content, so pop-ups, storage access, and cross-origin windows work without extra configuration. It also keeps every Klarna feature available, including those that require the top-level context.
Load Klarna SDK in an iframe
Only embed Klarna in an iframe if your architecture requires it — loading at the top level avoids the browser restrictions that apply to framed content. If you must use an iframe, follow this guidance closely to keep the integration robust and deliver a best-in-class customer experience.
Klarna's purchase flow opens in a pop-up window on top of your checkout. If you load Klarna inside an iframe and apply the sandbox attribute, include the tokens below and delegate the payment permission with allow, so the browser can open that pop-up and keep the reference between the pop-up and your page.
MARKUP
1 2 3 4 5
<iframe src="https://your-checkout.example.com/checkout" sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-modals allow-storage-access-by-user-activation allow-top-navigation-by-user-activation" allow="payment"> </iframe>
sandbox tokenWhy it's required
allow-scriptsRun the Klarna SDK integration
allow-same-originKeep the iframe's own origin for storage, cookies, and network calls
allow-popupsOpen the Klarna pop-up window
allow-popups-to-escape-sandboxEnsure the Klarna pop-up is not itself sandboxed
allow-formsSubmit the payment form
allow-modalsShow modal dialogs where needed
allow-storage-access-by-user-activationLet Klarna access browser storage after a customer interaction
allow-top-navigation-by-user-activationNavigate the top-level page to the Hosted Payment Page when the redirect-based flow is used
The allow attribute is separate from sandbox — it delegates a browser permission to the framed document.
allow directiveWhy it's required
paymentDelegate the Payment Request API to the iframe. The permission defaults to the top-level document only, so a framed integration has to be granted it explicitly.
Where possible, host the iframe on the same origin as your checkout page. It reduces the third-party-context storage and redirect issues involved in this class of failure. This is a reliability recommendation, not a security boundary — with allow-scripts and allow-same-origin a same-origin frame can reach its parent, so do not treat the sandbox as an isolation control.
Also, when loading inside an iframe:
  • Load the Klarna SDK integration only once per page — loading it more than once can leave overlapping widgets and lock page scrolling.
  • Expand the iframe to full screen while the purchase flow is open — required so Klarna can render the recovery backdrop and, where pop-ups are not possible, the flow itself. A frame cannot resize itself, so the parent page must apply the resize: have the framed page notify the parent with postMessage when the flow opens and closes, and have the parent expand the frame to the full viewport and restore its inline size afterwards. Validate the origin on both sides — the framed page posts to the exact parent origin, and the parent checks event.origin before it resizes. The example below shows the handshake.
  • Some Klarna features are not available inside an iframe — pre-purchase personalization and conversion-boost placements require the top-level context. Use the top-level integration if you rely on them.
From the framed checkout page, tell the parent when Klarna's flow opens and closes. Post to the exact parent origin — never *.
JAVASCRIPT
1 2 3 4 5 6 7 8 9 10
const PARENT_ORIGIN = 'https://parent.example.com'; function startKlarnaFlow() { // Ask the parent to expand the frame, then open the purchase flow. window.parent.postMessage({ type: 'klarna:flow-open' }, PARENT_ORIGIN); Klarna.Payments.authorize({}, { /* billing_address, shipping_address, ... */ }, function (res) { // Restore the frame once the authorize() callback runs. window.parent.postMessage({ type: 'klarna:flow-close' }, PARENT_ORIGIN); console.debug(res);
The framed page signals the parent around the purchase flow.
From the parent page, expand the iframe to the full viewport while the flow is open, then restore its inline size. Validate event.origin before acting on any message.
JAVASCRIPT
1 2 3 4 5 6 7 8 9 10
const FRAME_ORIGIN = 'https://your-checkout.example.com'; const frame = document.getElementById('klarna-frame'); const inlineStyle = frame.getAttribute('style') || ''; window.addEventListener('message', function (event) { if (event.origin !== FRAME_ORIGIN) return; if (event.data && event.data.type === 'klarna:flow-open') { frame.style.cssText = 'position:fixed;inset:0;width:100vw;height:100vh;border:0;z-index:2147483647;';
The parent resizes the iframe when the framed page signals.

Initialize the SDK

Initialize the SDK by making an init() call and passing the client_token from the Initiate a payment step.
JAVASCRIPT
1 2 3
Klarna.Payments.init({ client_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.dtxWM6MIcgoeMgH87tGvsNDY6cH' })
A sample call to initialize the SDK.
The client_token relies on the created session, which expires after 48 hours. The purchase might fail after this time.

Add a container to your page

Add a container in the HTML file of your checkout page. This container specifies where to place the widget.
MARKUP
1
<div id="klarna-payments-container"></div>
A sample widget container.

Display Klarna

At checkout, your customers can choose to pay with Klarna. Then, a pop-up window opens where your customers log into their Klarna account and select their preferred Klarna payment option.
You need to use our JavaScript SDK to display Klarna in your checkout. This interaction is possible through the load() call happening on the client side.
The following information is applicable for both scenarios, one-time and recurring payments.

Load() call

At checkout, display Klarna as a payment option by using the load() call. Specify the following parameter:
For more information about load() call parameters, refer to the Klarna payments SDK reference.
JAVASCRIPT
1 2 3 4 5 6 7 8 9
Klarna.Payments.load( { container: '#klarna-payments-container' }, {}, function (res) { console.debug(res); } )
A sample load() call to display Klarna as a payment option.

Best practices for the load() call

For a better customer experience, call load() when loading your checkout. In this way, you ensure that the container of Klarna payments loads immediately in a hidden container, and it's ready to appear when needed.
Don't forget to use the Klarna logo that you received in Step 1: Initiate a payment and add the payment option name. From the payload you received in Step 1, use:
  • identifier to dynamically load the payment option
  • name to display the correct and localized payment option title
  • asset_urls to contain the Klarna logo
You can manage the name and Klarna descriptor when adding the Klarna payments in your checkout and use the name and asset_urls returned in Step 1: Initiate a payment.

Load responses

After processing the load() call, the callback function runs. The JavaScript callback is an object containing the following parameters:
  • show_form, indicating if Klarna payments is available
  • error, containing details of potential error messages
The show_form boolean parameter is the response flag to the load() call. It tells your checkout whether the customer can pay with Klarna. Always listen to it so you can react when Klarna is unavailable.
There are two potential cases that you need to handle based on the response flag:
  • Success response: Your checkout offers Klarna payments.
  • Error response: Your checkout is not able to offer Klarna payments.

Success response

If the response flag is show_form: true, your checkout displays Klarna as a payment option for this purchase. This is the standard response.
JSON
1 2 3
{ "show_form": true }
A sample success response to offer Klarna payments.

Error response

If the response flag is show_form: false, your checkout is not able to offer Klarna as a payment option.
This negative response results from the pre-assessment that Klarna runs for the purchase.
JSON
1 2 3
{ "show_form": false }
A sample error response when Klarna payments are unavailable.
To handle the negative response, you can set up one of the following visual arrangements in your checkout:
  • Hide the Klarna option from the checkout.
  • Gray out the Klarna option and disable clicking.
  • Keep the Klarna option and accept an error message. Klarna informs the customer that this option is not available.

Get authorization

When your customer selects Klarna to pay, you need to use our JavaScript SDK to get authorization for the purchase.
In this step, you send all the necessary customer details for Klarna to assess and decide whether or not to accept this purchase. When the authorization is successful, you receive an authorization token as a response, useful for Step 3: Create an order.
The authorization is possible through the authorize() call happening on the client side. You should also implement the authorization callback so that you receive the authorization token on the server side and no authorization is missed.
The following information is useful for both scenarios, one-time and recurring payments.

Authorize() call

Get authorization for the purchase by using the authorize() call. We recommend sending the following parameters in the data object of the authorize call:
  • billing_address, containing the customer's billing address.
  • shipping_address, containing the customer's shipping address. If you don't provide a shipping address, we copy the billing address and use it as the shipping address.
If no billing or shipping address is provided, new Klarna customers have to manually enter their full billing address on the Klarna payment page. Providing the billing address in the authorize() call enables Klarna to prefill the signup form for new customers.
We recommend avoiding any delays or asynchronous operations (for example, sending calls to your server) between the customer clicking the Buy button and you calling authorize(). Longer delays or asynchronous operations between the actual customer interaction and the authorize() call cause the browser to block the Klarna pop-up from opening.
If you load Klarna inside an iframe, expand the iframe to fill the full viewport while the purchase flow is open. This lets Klarna render its backdrop — the recovery mechanism that lets the customer reopen or locate the Klarna pop-up if the browser blocked it or the pop-up was lost among their other tabs — and, on surfaces where a pop-up is not possible (such as a WebView), render the purchase flow inside the iframe. If the iframe stays at its inline size, neither recovery path can display and customers who lose the pop-up drop out of the checkout.
On mobile browsers, where pop-ups and cross-origin windows are the most restricted, we recommend the redirect-based flow (Hosted Payment Page) rather than the pop-up for the most reliable experience. To use it, create a Hosted Payment Page session and redirect the customer to Klarna instead of calling authorize() in the browser — see the Hosted Payment Page integration guide.
To update the Klarna session, provide all necessary information when calling authorize(). If you need to update your server-side session, we recommend doing so when the customer returns from Klarna's purchase flow.
JAVASCRIPT
1 2 3 4 5 6 7 8 9 10
Klarna.Payments.authorize( {}, { billing_address: { given_name: "Alice", family_name: "Test", email: "customer@email.se", phone: "+46701740615", street_address: "Södra Blasieholmshamnen 2", postal_code: "11 148",
A sample authorize() call.
In some cases, Klarna requires additional information about the customer and purchase. We recommend you send it in the authorize() call. For more information, see the Extra merchant data section.
For GDPR (General Data Protection Regulation) reasons, you shouldn't send customer data before the authorize() call.
Klarna uses all this information to make the fraud assessment. To see what data you need per market and how to format it, check the customer data requirements.

Customer interaction during the call

During the authorize() call and until you receive the callback, Klarna runs a purchase flow that includes a fraud assessment. You need to visually indicate to your customer that an ongoing process is happening. For a better customer experience, we suggest:
  • Avoiding another authorize() call (for example, disable the buy button)
  • Showing your customer that the order is in progress (for example, show a loading spinner)
  • Preventing your customer from changing the order or billing details (for example, lock the input fields on your page).

Authorization callback

Implement the server-side authorization callback so you always receive the authorization_token and session_id, even when client-side communication fails. You need both values to create the order, so the callback keeps the checkout reliable if the customer's browser drops the response.
JSON
1 2 3 4
{ "authorization_token": "0eb73d2c-d55a-5358-9080-ddc3903e3941", "session_id": "e4b81ca2-0aae-4c16-bcb2-29a0a088a35b" }
A sample server-side callback request from Klarna.
For more details, see the authorization callbacks documentation.

Authorization responses

There are three potential cases that you need to handle based on the response:
  • Success response: The purchase is approved.
  • Fixable error response: The customer needs to adjust and try again.
  • Error response: The purchase is not approved and you can't display Klarna as a payment option.

Success response and authorization callback

If the response is approved: true, Klarna has approved the authorization for this purchase and as a response you will receive the response including:
  • approved, containing the authorization result. It's a boolean value that indicates approved or denied.
  • show_form, showing the availability of Klarna as a payment option. It's a boolean value that indicates displayed or hidden.
  • authorization_token, containing the token that allows you to place the order. This is only returned if it's an approved authorization.
  • error, containing details of potential error messages.
authorization_token allows you to create an order for both scenarios, recurring and one-time payments. The token is valid for 60 minutes.

Fixable error response

If the response of the authorize is not successful with show_form: true and an error object containing invalid_fields, something fixable is wrong and the customer needs to take action. An error message is displayed asking the customer to make corrections before you re-authorize the purchase. The error message points out which fields are incorrect.
It's also possible that the response is approved: false and show_form: true, but the callback doesn't include error. This means the customer has terminated a required interaction in the widget, such as authentication or sign-up flows. In this case, you should keep Klarna visible so that the customer can make another purchase attempt.
JSON
1 2 3 4 5 6 7 8 9 10
{ "approved": false, "show_form": true, "error": { "invalid_fields": [ "billing_address.street_address", "billing_address.city", "billing_address.given_name", "billing_address.postal_code", "billing_address.family_name",
A sample fixable error response.
We suggest you use the error message in the authorize() response to highlight a specific input field on your page.

Error response

If the response is show_form: false, your checkout is not able to offer Klarna as a payment option. You should disable Klarna from your checkout, and your customer might select another payment option.
This negative response results from the pre-assessment that Klarna runs for the purchase.
JSON
1 2 3 4
{ "approved": false, "show_form": false }
A sample error response.