Onfido LogoOnfido Logo


Onfido Smart Capture Web SDK

Build Status npm version


The Onfido Smart Capture SDKs provide a set of screens and functionality allowing applications to implement user identity verification flows. Each SDK contains:

  • Carefully designed UX to guide your customers through the different photo or video capture processes
  • Modular design to help you seamlessly integrate the different photo or video capture processes into your application's flow
  • Advanced image quality detection technology to ensure the quality of the captured images meets the requirement of the Onfido identity verification process, guaranteeing the best success rate
  • Direct image upload to the Onfido service, to simplify integration
  • A suite of advanced fraud detection signals to protect against malicious users

All Onfido Smart Capture SDKs are orchestrated using Onfido Studio workflows with only minor customization differences between the available platforms.

The Onfido Web SDK is specifically designed for integrating web applications and easily managing cross-device experiences.

Various views from the SDK

Environments and testing with the SDK

Two environments exist to support the Onfido SDK integrations:

  • 'sandbox' - to be used for testing with sample documents
  • 'live' - to be used only with real documents and in production apps

The environment being used is determined by the API token that is used to generate the necessary SDK token.

Going Live

Once you are satisfied with your integration and are ready to go live, please contact Onfido's Customer Support to obtain a live API token. You will have to replace the sandbox token in your code with the live token.

Check that you have entered correct billing details inside your Onfido Dashboard, before going live.

Importing the library & staying up-to-date

The Onfido Web SDK can be added to your project in two ways:

  • Directly in the web application in a script tag or as an import
  • As part of your project build as a library imported from NPM

To benefit from the latest features and patches released by Onfido and minimize the size of the script used, it is highly recommended to use an integration method that leverages the Onfido CDN, as detailed in the following sections.

Note that while Onfido hosts the CDN and ensures the script availability at runtime, any project using the SDK library from NPM would require its hosting.

Direct CDN integration

The quickest and simplest way to integrate the Onfido Web SDK is to use the Onfido-hosted library.

From SDK 12.3.1 onwards, the version number you subscribe to can vary, depending on your needs:

  • subscribing to a major release (e.g. v14) means Onfido will update to the latest available patch and minor release
  • subscribing to a minor level release (e.g. v14.11) means Onfido will update to the latest available patch release
  • subscribing to a specific patch release (e.g. v14.11.0) will fix the library files to that SDK release

Importing the SDK in an html script tag

1<!-- Replace "<version>" with the actual SDK version you want to use, example: v14.11.0 -->
2<script src="https://sdk.onfido.com/<version>" charset="utf-8"></script>

Note that prior to version 12.3.1, the CDN path was https://assets.onfido.com/web-sdk-releases/<version>/onfido.min.js.

Also note that from version 14 onwards, a separate stylesheet is no longer required as it will be included with the default library.

Importing the SDK with a JavaScript import directive

The library can also be invoked directly within an object or component:

1// ES6 module import
2import { Onfido } from 'onfido-sdk-ui'
4// commonjs style require
5var Onfido = require('onfido-sdk-ui').Onfido

The CSS style will be included inline with the JS code when the library is imported.

Note: The library is Browser only, it does not support the Node Context.

Integrating with an NPM package

NPM is a public repository of libraries available for download and integration into web/native apps. Onfido has been publishing all its SDKs there for convenience to customers.

The Web SDK version 14 will continue with the existing package name:

1npm install onfido-sdk-ui


1yarn add onfido-sdk-ui

From version 14 onwards, the onfido-sdk-ui package will, by default, be connected to the Onfido CDN. In addition to the benefits of using a CDN and the library being directly in your build process, core functions will also be typed when used with Typesript.

Full bundles that consist of the full library will also be made available via NPM.

From version 14 onwards, "split bundles" are no longer supported. Onfido recommends the use of either the direct or NPM CDN integration.

NPM package version pinning

In order to facilitate integration and A/B tests, the CDN-powered NPM package will also optionally support the ability to specify a version (major, minor or patch) of the Onfido Web SDK library.

More details are provided in the SDK version pinning section below.


From version 6.5.0 onwards, TypeScript is officially supported, providing types for:

  • init() method
  • options argument (SdkOptions) and return object (SdkHandle) of init() method
  • Arguments (SdkResponse and SdkError) for onComplete() and onError() callbacks
  • steps option (StepTypes and StepConfig)
  • language option (SupportedLanguages and LocaleConfig)
  • region option (ServerRegions)

Loading the Onfido flow

To load the Onfido flow, add an empty HTML element for the modal interface to mount itself on:

1<div id="onfido-mount"></div>

With the configuration in an accompanying script:

2 token: '<YOUR_SDK_TOKEN>',
3 containerId: 'onfido-mount',
4 //containerEl: <div id="root" />, an ALTERNATIVE to `containerId`
5 onComplete: function (data) {
6 console.log('everything is complete')
7 },
8 workflowRunId: '<YOUR_WORKFLOW_RUN_ID>',

You can see an example integration of the Onfido Web SDK in our sample app.

You may also optionally specify a different container or identifier to load the Onfido flow:

  • containerId {String} - optional

    ID value of the container element that the UI will mount to. The element itself needs to be an empty element. The default ID is onfido-mount. If your integration needs to pass the container element itself, use containerEl as described next.

  • containerEl {Element} - optional

    Container element that the UI will mount to. This needs to be an empty element. This can be used as an alternative to passing in the container ID string previously described for containerId. Note that if containerEl is provided, then containerId will be ignored.

Integrating in a webview

While webviews provide a lightweight integration and simplify cross-platform development, they have limitations in terms of accessing device features such as the camera, microphone, and local files as they rely on the webview engines provided by the operating system. As such webviews don’t offer the same level of performance and user experience as the functionality of the Onfido mobile SDKs in native apps.

Where possible, Onfido recommends using its native mobile SDKs for optimal performance.

Please refer to this guide for more details about how to integrate the Onfido Web SDK in a webview.

Initializing the SDK

The Web SDK has multiple initialization and customization options that provide flexibility to your integration, while remaining easy to integrate.

Note that from version 14, it will no longer be possible to change initialization options at runtime as was previously allowed with the setOption() function.

Defining a workflow

Onfido Studio is the platform used to create highly reusable identity verification workflows for use with the Onfido SDKs. For an introduction to working with workflows, please refer to our Getting Started guide, or the Onfido Studio product guide.

SDK sessions are orchestrated by a session-specific workflow_run_id, itself derived from a workflow_id, the unique identifier of a given workflow.

For details on how to generate a workflow_run_id, please refer to the POST /workflow_runs/ endpoint definition in the Onfido API reference.

Note that in the context of the SDK the workflow_run_id property is referred to as workflowRunId.

SDK authentication

The SDK is authenticated using SDK tokens. As each SDK token must be specific to a given applicant and session, a new token must be generated each time you initialize the Onfido Web SDK.

  • token {String} - required

    A JWT is required in order to authorize with the Onfido WebSocket endpoint. If the SDK token is missing, an exception will be thrown.

For details on how to generate SDK tokens, please refer to POST /sdk_token/ definition in the Onfido API reference.

SDK tokens have a fixed expiry of 90 minutes.

Note: You must never use API tokens in the frontend of your application as malicious users could discover them in your source code. You should only use them on your server.

Version pinning

Based on the same major version, the minor and patch versions of the library can be specified in the Onfido.init() object.

  • version {String} - optional

    The specific version of the Onfido Web SDK that should be loaded as part of this initialization. A full version (e.g. v14.12.1) or just a minor version (e.g. v14.13) can be specified. When a minor version is specified, the latest patch version for that minor release will be loaded. Example: version: "14.12.1"

Note: This parameter is ineffective when the library is imported as a full bundle from NPM (as opposed to the default CDN-powered NPM package).

Styling customization

The Onfido Web SDK supports customization options to adjust the fonts, the SDK main container, buttons, links, icons, background color and popups.

To customize the SDK, you can pass the required CSS values to the customUI object, in the root of the Onfido.init() object.

  • customUI {Object} - optional

    Object containing optional CSS values for the supported UI customization options. The sample below lists all possible options with some example values.

2 "customUI": {
3 "borderRadiusButton": "56px",
4 "borderStyleSurfaceModal": "0px",
5 "fontWeightBody": 400,
6 "fontSizeBody": "16px",
7 "fontSizeSubtitle": "16px",
8 "fontSizeTitle": "40px",
9 "colorBackgroundSurfaceModal": "transparent",
10 "colorBackgroundIcon": "transparent",
11 "colorBorderLinkUnderline": "transparent",
12 "colorBackgroundLinkActive": "transparent",
13 "colorBackgroundLinkHover": "transparent",
14 "colorBackgroundDocTypeButton": "transparent",
15 "colorContentBody": "rgb(255,255,255)",
16 "colorContentTitle": "rgb(255,255,255)",
17 "colorContentSubtitle": "rgb(255,255,255)",
19 "colorContentButtonPrimaryText": "rgb(10,11,13)",
20 "colorBackgroundButtonPrimary": "rgb(55, 115, 245)",
21 "colorBackgroundButtonPrimaryHover": "rgb(55, 115, 245)",
22 "colorBackgroundButtonPrimaryActive": "rgb(55, 115, 245)",
24 "colorContentButtonSecondaryText": "rgb(255,255,255)",
25 "colorBackgroundButtonSecondary": "rgb(50,53,61)",
26 "colorBackgroundButtonSecondaryHover": "rgb(30,32,37)",
27 "colorBackgroundButtonSecondaryActive": "rgb(30,32,37)",
28 "colorContentLinkTextHover": "rgb(55, 115, 245)",
29 "colorBorderDocTypeButton": "rgb(20, 21, 25)",
30 "colorBackgroundDocTypeButtonHover": "rgb(30,32,37)",
31 "colorBackgroundDocTypeButtonActive": "rgb(30,32,37)",
32 "colorContentDocTypeButton": "rgb(255,255,255)",
33 "colorIcon": "rgb(55, 115, 245)",
34 "colorContentInfoPill": "rgb(10,11,13)",
35 "colorBackgroundInfoPill": "rgb(55, 115, 245)",
36 "colorBackgroundSelector": "red",
37 "colorBackgroundDropdownItemHover": "rgb(30,32,37)",
38 "colorInputOutline": "rgb(87, 139, 250)",
39 "colorContentButtonTertiaryText": "rgb(255,255,255)",
40 "colorContentInput": "blue",
41 "colorBackgroundInput": "green",
42 "colorBorderInput": "yellow"
43 }

For use in a webview on a mobile device, it is recommended to set up the SDK to use the full screen of the device. Otherwise, there may not be enough room to display all critical elements of the SDK.

Note that from version 14, the Onfido SDK options to load the screens in a modal have been deprecated. If you wish to load the Onfido screens in a modal you will have to define it as part of your own integration.


The Onfido SDK allows for two co-branding options that affect the display of the Onfido logo at the bottom of the Onfido screens.

For further customization, please contact your Onfido Solution Engineer or Customer Success Manager.

Text co-branding

  • cobrand {Object} - optional

    The most effective way to add your brand to the footer watermark, is by use of the cobrand property under enterpriseFeatures. This property takes a text parameter.

    Example of text cobranding

2 ...
3 enterpriseFeatures: {
4 cobrand: {
5 text: "Onboarding, Inc."
6 }
7 },

Logo co-branding

  • logoCobrand {Object} - optional

    As an alternative to cobrand, you may specify a set of images to be defined in the logoCobrand property under enterpriseFeatures. You must provide the path to an image for use in 'dark' mode and a separate image for 'light' mode. Both images must have a resolution of 144x32.

2 ...
3 enterpriseFeatures: {
4 logoCobrand: {
5 darkLogoSrc: "https://YourLogoImageUrlOrFilePath",
6 lightLogoSrc: "https://YourLogoImageUrlOrFilePath",
7 }
8 },

Language selection

The Onfido SDK supports and maintains translations for over 40 languages in its SDKs.

  • language {String || Object} - optional

    You can customize the language displayed on the SDK by passing a string or object. If language is not present at the root of the Onfido.init() call, the SDK will use the browser's language setting. If the browser's language is not supported by Onfido, the SDK will default to English (en_US).

1language: 'pt_BR' | 'es'

For the list of languages supported by Onfido, please refer to our SDK customization guide.

Language customization

In addition to selecting default languages for the SDK session, the SDK can also be displayed in a custom language for locales that Onfido does not currently support or for the addition of custom text, specific to your integration needs. This can be achieved by setting the following options in the language object:

localerequired A locale tag.This is required when providing phrases for an unsupported language. You can also use this to partially customize the strings of a supported language (e.g. Spanish), by passing a supported language locale tag (e.g. es_ES). For missing keys, the values will be displayed in the language specified within the locale tag if supported, otherwise they will be displayed in English. The locale tag is also used to override the language of the SMS body for the cross-device feature. This feature is owned by Onfido and currently only supports English, Spanish, French and German.
phrasesrequired An object containing the keys you want to override and the new values.Keys can be passed as a nested object or as a string using the dot notation for nested values. Refer to the next section for instructions on how to find the right keys.
mobilePhrasesoptional An object containing the keys you want to override and the new values.The values specified within this object are only visible on mobile devices. Note: support for standalone mobilePhrases key will be deprecated soon. Consider nesting it inside phrases if applicable.
1language: {
2 locale: 'en_US',
3 phrases: {
4 'capture.driving_licence.instructions': 'This custom string will appear by default'
5 },
6 mobilePhrases: {
7 'capture.driving_licence.instructions': 'This custom string will only appear on mobile'
8 }

Identifying text keys in the Onfido screens

In order to identify text that can be overridden and locate their exact keys, you should use a browser inspector and indentify div blocks with the attribute name data-i18n-token.

Example of how to use an html inspector to find a text key

Cross-device navigation

The Web SDK offers a cross-device flow where desktop users are directed to continue on their mobile device browser to complete the capture process. This provides a vastly improved image quality versus a typical desktop webcam and increases the likelihood of successful live capture.

Force cross-device flow

Three options are offered to the user to resume the flow on a mobile device browser:

  • QR code that can be scanned with a camera app (default)
  • 'Copy Link' feature that can be copy/pasted into a web browser
  • One-time SMS link that can be sent diretly to the user's mobile phone

Regardless of the cross-device method, the secure URL is unique to this session.

At the end of the capture process, users will be instructed to revert back to their desktop to complete the SDK flow.

Note that during a capture sequence on a desktop device, if a camera cannot be detected, the user is forward by default to the cross-device flow in order to attempt the capture on another device.

Enforcing cross-device navigation

In order to optimize the capture quality, it is recommended to enforce the cross-device flow. The option is available in Onfido Studio, configurable in the workflow builder.

Cross-device can also be enforced at run-time using the following initialization option:

  • crossDevicePolicy {String} - optional

    By default, the cross-device flow is not enforced but shown to the user alongside a button to upload a document instead. You can force the user to capture a document or face on a mobile device by either:

  • setting the option globally (across all workflow runs) in the workflow builder

  • setting the crossDevicePolicy initialization option at runtime to either force or disable to completely remove the option

    1crossDevicePolicy: 'force'

Customizing the cross-device experience

In addition to forcing the cross-device flow, the cross-device experience can be further customized during the SDK initialization with the following options:

  • _crossDeviceLinkMethods {List<String>} - optional

    You can specify which of the three cross-device link options are presented to the user by adding any of qr_code, copy_link and/or sms to the _crossDeviceLinkMethods using a , as a separator. The first element of the list will be the default option shown to the user. Note the underscore at the start of the string.

    1_crossDeviceLinkMethods: ['qr_code', 'copy_link', 'sms']
  • smsNumberCountryCode {String} - optional

    You can change the default country for the SMS number input by passing the smsNumberCountryCode option at the root of the Onfido.init() call when the SDK is initialized. The value should be a string containing a 2-character ISO country code. If empty, the SMS number country code will default to GB.

    1smsNumberCountryCode: 'US'
  • userDetails {Object} - optional

    The following user details can be specified ahead of time, so that the user doesn't need to provide the information themselves:

    • smsNumber (optional) : The user's mobile number can be added to the optional userDetails object at the root of the Onfido.init() call. The value should be a string containing the mobile number with a country code.
    1userDetails: {
    2 smsNumber: '+447500123456'
  • crossDeviceClientIntroProductLogoSrc {String} - optional

    You can customize the icon by adding your company or product logo to be displayed instead of the default SDK icon image with this option. The image referenced in the path should be no more than 144px in both height and width.

    2 ...
    3 crossDeviceClientIntroProductLogoSrc: "path://to/logo/image/file",

Note that from version 14, the crossDeviceClientIntroProductName option used in previous versions to modify just the customer name in the cross-device intro screen has been deprecated. Instead, you should use the standard language customization process to override the subtitle of the screen.

Completing a session

Handling callbacks

When the Onfido SDK session will conclude, one of two callback functions may be triggered:

  • onComplete: the session was successful with at least 1 document captured
  • onError: the session terminated unexpectedly

For advanced callbacks used for user analytics and returning submitted media, please refer to the Advanced Callbacks section of this document.

onComplete {Function} - optional

Callback that fires when the flow has successfully been executed with at least 1 document capture.

2 token: "<YOUR_SDK_TOKEN>",
3 ...
4 onComplete: function (data) {
5 console.log("everything is complete");
6 },

The data object contains properties of the documents and face images uploaded by the user during the SDK session. The properties contain a unique identifier that can be used to retrieve the full document or face capture using the corresponding document, live_photos (for 'standard' selfies) or live_videos (for 'video' or 'motion' captures) endpoints defined in the API reference.

2 "document_front": {
3 "id": "<DOCUMENT_ID_FRONT>",
4 "type": "driving_licence",
5 "side": "front"
6 },
7 "document_back": {
8 "id": "<DOCUMENT_ID_BACK>",
9 "type": "driving_licence",
10 "side": "back"
11 },
12 "face": {
13 "id": "<FACE_ID>",
14 "variant": "standard"
15 },
16 "poa": {
17 "id": "<POA_DOCUMENT_ID>",
18 "type": "utility_bill"
19 }

For two-sided documents such as driving_licence and national_identity_card, the object will also contain a document_back property representing the reverse side.

For the face step, an object is returned with the variant used for the face capture,'standard' | 'video' | 'motion'.

onError {Function} - optional

Callback that fires when an error occurs. The callback returns the following error types:

  • invalid_token This error will be returned when the SDK token is invalid or missing.

    2 type: "invalid_token",
    3 message: "The token is invalid."
  • expired_token This error will be returned when a token has expired. This error type can be used to provide a new token at runtime.

    2 type: "expired_token",
    3 message: "The token has expired, please request a new one"
  • expired_trial This error will be returned when the trial has expired.

    2 type: "expired_trial",
    3 message: "The trial period is expired."
  • geoblocked_request This error will be returned when the request is geo-blocked.

    2 type: "geoblocked_request",
    3 message: "The request is not allowed from this location."
  • permissions_unavailable This error will be returned if the SDK was unable to access or request the necessary permissions. This may occur when the Web SDK is loaded within a webview or other custom browsers.

    2 type: "permissions_unavailable",
    3 message: "Unable to retrieve or access required user permissions"
  • unsupported This error will be returned when the a module is not supported in the current environment.

    2 type: "unsupported",
    3 message: "The module is not supported in the current environment."
  • unsupported_feature This error will be returned when a feature is not supported.

    2 type: "unsupported_feature",
    3 message: "The feature is no longer supported."
  • invalid_sdk_parameter This error will be returned when the SDK is initialized with invalid parameters.

    2 type: "invalid_sdk_parameter",
    3 message: "The SDK is initialized with invalid parameters."
  • unsupported_sdk_version This error will be returned when the workflow is not supported by the SDK version.

    2 type: "unsupported_sdk_version",
    3 message: "The SDK version is not compatible with the workflow."
  • no_camera This error will be returned when the camera is not available and no other capture method is available.

    2 type: "no_camera",
    3 message: "The camera is not available."
  • user_consent_denied This error will be returned when the user exits the flow because they declined the consent.

    2 type: "user_consent_denied",
    3 message: "The user has declined the consent."
  • exception This will be returned for all unknown errors, including:

    • timeout and server errors
    • unexpected javascript errors

    This data can be used for debugging purposes.

    2 type: "exception",
    3 message: "The request could not be understood by the server, please check your request is correctly formatted"
    4 exception: Error
    • workflow_abandoned This error will be returned when the user has abandoned the workflow run and it has timed out.
    2 type: "workflow_abandoned",
    3 message: "The workflow has been abondoned."
    • workflow_error This error will be returned when there is an error with workflow run.
    2 type: "workflow_error",
    3 message: "The workflow run is invalid."

Note that from version 14 onwards, the optional onUserExit callback, that was used to return the USER_CONSENT_DENIED message, has been deprecated and merged with the onError callback, as detailed above.

SDK tear-down

If you have embedded the SDK inside a single page app, you can call the tearDown function to remove the SDK completely from the current webpage. It will reset the state and you can safely re-initialize the SDK inside the same webpage later on.

1onfidoOut = Onfido.init({...})
3await onfidoOut.tearDown()

⚠️ Warning: The tearDown method is a Promise. If you plan on mounting the SDK a second (or nth) time, please await the promise first.

1onfidoOut = Onfido.init({...})
2await onfidoOut.tearDown()
3onfidoOut2 = Onfido.init({...})

Generating verification reports

While the SDK is responsible for capturing and uploading the user's media and data, identity verification reports themselves are generated based on workflows created using Onfido Studio.

For a step-by-step walkthrough of creating an identity verification using Onfido Studio and our SDKs, please refer to our Quick Start Guide.

If your application initializes the Onfido Web SDK using the options defined in the Advanced customization section of this document, you may create checks and retrieve report results manually using the Onfido API. You may also configure webhooks to be notified asynchronously when the report results have been generated.

Advanced flow customization

This section on 'Advanced customization' refers to the process of initializing the Onfido Web SDK without the use of Onfido Studio. This process requires a manual definition of the verification steps and their configuration. The steps parameter is mutually exclusive with workflowRunId. The other parameters under Onfido.init() remain the same.

Note that this initialization process is not recommended as the majority of new features are exclusively released for Studio workflows.

  • steps {List<String>} - optional

    The list of user verification steps, in order of appearance. Each step can either be specified as a string (when no customization is required) or an object (when customization is required). Customization options are described in the following sections.

From the possible steps listed below, only document is required:

welcomeWelcome screen shown to the user with preliminary instructions. Customization options include modification to the text elements and instructions shown to the user.
documentSet of screens that control the capture via photo or upload of the user's document. Numerous customization options are available to define the document list presented to the user and the overall capture experience.
faceSet of screens that control the capture of a selfie, video or motion of the user. The customization options allow the selection of the capture variant as well as fallback options.
completeScreen shown to the user at the end of the flow. Customization options include modifications to the text elements shown to the user.
2 token: "<YOUR_SDK_TOKEN>",
3 ...
4 steps: [
5 {
6 type: "welcome",
7 options: {
8 title: "Open your new bank account",
9 },
10 },
11 "document",
12 "face",
13 ];

welcome step

This step is the introduction screen of the SDK. It introduces the process and prepares the user for the steps they will need to complete. These steps can be specified to match the flow required.

While this screen is optional, we only recommend its removal if you already have your own identity verification welcome screen in place.

The custom options are:

  • title (string)
  • descriptions ([string])
  • nextButton (string)

document step

The Document Capture step is typically organised in three parts:

  • The issuing country and document type selection
  • The camera capture
  • The document review and upload

Note that the document step is mandatory.

The customization options available all relate to the country and document type selection screen. By default, the selection screen is shown with the country selection being empty.

Choose documents type The above images are for web SDK versions 8.3.0+

Depending on the customization options defined in this step or the 'allowed countries' defined in your Dashboard, either the country or document type selection screens might not be shown:

  • The country selection screen will not be shown if only 1 country is selected or if only passports are allowed
  • The document selection screen will not be shown if only 1 document type is specified

You can specify allowed issuing countries and document types for the document capture step in one of three ways:

  • Onfido Studio: If you are using Onfido Studio, this is configured within the Document Capture task, as documented in the Studio Product Guide

  • Dashboard : Otherwise, the recommended approach is to apply this configuration globally in the Dashboard under Accounts \ Supported Documents. This option also ensures that the list is enforced as part of the Document Report validation. Any document that has been uploaded by an end user against your guidance will result in a Document Report sub-result of "rejected" and be flagged as Image Integrity > Supported Document.

    The Supported Documents tab in Dashboard

  • Run-time: For run-time configuration, the following options can be defined under the document step:

    • documentTypes {Object} - required

      The list of document types visible to the user can be filtered by using the documentTypes option. When documentTypes is not defined, the default value for each document type is true. When documentTypes is defined, it will override the default values. Absent types are considered false.

    • country {String} - optional

      Document country can be specified per document type. The country configuration for a document type allows you to specify the issuing country of the document as a string containing a 3-letter ISO 3166-1 alpha-3 country code.

      If documentTypes only includes one document type with a country value, users will not see the document selection screen and instead will be taken directly to the capture screen.

      ⚠️ Note: the null value is deprecated and has no effect.

      ⚠️ Note: Passports have the same format worldwide so the SDK will not show the country selection screen even if they are not restricted by country (e.g. passport: true).

    • hideCountrySelection {Boolean} - optional

      It is possible to completely remove the country selection screen, showing instead the list of all possible document types directly to the user by setting hideCountrySelection to true. This is not recommended as it will prevent document-specific optimization of the flow and detailed analytics.

2 "steps": [
3 "welcome",
4 {
5 "type": "document",
6 "options": {
7 "documentTypes": {
8 "driving_licence": {
9 "country": "ESP"
10 },
11 "national_identity_card": true,
12 "residence_permit": true
13 }
14 }
15 },
16 "complete"
17 ]

In the example above only Spanish (ESP) driving licences, and national identity cards and residence permits for all countries will be shown

Please note:

  • Hard coding any document type and issuing country configuration in your SDK integration will fully override the Dashboard-based settings
  • Currently, only passport, national ID card, driving licence and residence permit are visible for document selection by the end user in the SDK. If you nominate other document types in your Dashboard (visa, for example), these will not be displayed in the user interface
  • If you need to add other document types to the document selection screen, you can mitigate this limitation in the near-term, using the Custom Document feature
  • If for any reason the configuration fails or is not enabled, the SDK will fallback to displaying the selection screen for the complete list of documents supported within the selection screens
Custom Documents

In case you require to capture a document that is not supported by Onfido or a supported document with a different name or scope (e.g. capturing the back of a two-sided document, even if it is not required for verification purposes), custom documents can be manually defined.

Note that if recognized, Onfido will still attempt to process them based on their detected classification.

  • genericDocumentTypes {Object} - optional

    If defined under the document step options, the custom document will be displayed at the bottom of the standard document types list after any other document types applicable to the other optional country / document type selection options defined in the previous sections.

    1genericDocumentTypes: [
    2 {
    3 id: 'my_single_side_document',
    4 title: 'My single side document',
    5 subTitle: 'Details about my document',
    6 country: 'ALB',
    7 pages: 1,
    8 },
    9 {
    10 id: 'my_two_sides_document',
    11 title: 'My two sides document',
    12 subTitle: 'Details about my document',
    13 country: 'ALB',
    14 pages: 2,
    15 },

    In the same way to other document types, if you wish to skip the document selection screen, you can add a single generic_document object which references the custom document declared in genericDocumentTypes.

    1documentTypes: {
    2 generic_document: {
    3 id: 'my_single_side_document',
    4 }

face step

This is the face capture step. Users will be asked to capture their face in the form of a photo, a video, or a motion capture. For photos and videos, they will also have a chance to check its quality before confirming.

Note that if a camera can’t be detected, the user will be forwarded to the cross-device flow in order to attempt to capture on another device. The cross-device flow will be presented to the user, before any optional fallback variants are assessed by the Web SDK.

face flow options
  • requestedVariant {String} - optional

    A preferred variant can be requested for this step, by passing the option requestedVariant: 'standard' | 'video' | 'motion', with the default version being standard. If requestedVariant is:

    • standard: a photo will be captured
    • video: a video will be captured
    • motion: a motion capture will be captured
    2 "steps": [
    3 "welcome",
    4 "document",
    5 {
    6 "type": "face",
    7 "options": {
    8 "requestedVariant": "motion"
    9 }
    10 },
    11 "complete"
    12 ]
  • showIntro {Boolean} - optional

    The instruction screen shown to the user at the beginning of the face capture step can be skipped for the video and standard variants. By default, the screen is shown (default to true). When disabled for the standard variant, the entire intro screen will be removed from the flow. When disabled for the video variant, the example video will be hidden in the intro screen, only showing the text instructions.

  • useMultipleSelfieCapture {Boolean} - optional

    This option only applies to the variant standard. By default the SDK will take additional selfie snapshots to help improve face similarity check accuracy. When disabled, only one selfie photo will be taken.

  • recordMotionAudio {Boolean} - optional

    This option only applies to the variant motion and enables the recording of the user's background audio. By default this is option is set to false.

face fallback options

The SDK will try to fulfil the request depending on camera availability, device capabilities and browser support on the user's device:

  • if the selected variant cannot be fulfilled and the user is on a desktop, the user will first be forwarded to the cross-device screen. This default step is introduced with version 14 of the Web SDK.
  • if a video cannot be taken on the mobile device, the face step can be configured to fallback to the standard variant (see photoCaptureFallback)
  • if Motion cannot be captured on the mobile device, an unsupported error will be thrown, which can be handled by onError().

If the SDK is initialized with the requestedVariant option for the face step, make sure you use the data returned in the onComplete callback to request the correct report when creating a check.

  • photoCaptureFallback {Boolean} - optional

    This feature only applies to the video variant. By default, this option is true and allows end-users to capture a selfie if their mobile browser does not support MediaRecorder (which is required by the other variants). When disabled, we will return an unsupported browser error if the end-user browser doesn’t support MediaRecorder.

complete step

This is the final completion step. The screen displays a completion message to signal the next steps to the user. This is an optional screen. The custom options are:

  • message (string)
  • submessage (string)

Advanced callbacks

The following features must be enabled for your account before they can be used. For more information, please contact your Onfido Solution Engineer or Customer Success Manager.

Custom media callbacks

Custom media callbacks enable you to control the data collected by the Onfido SDK by using callbacks that are invoked when the end user submits their captured media. The callbacks provide all of the information that would normally be sent directly to the Onfido API and expect a promise in response, that controls what the SDK does next.

Once custom media callbacks are enabled for your account, you will need to add the optional enterpriseFeatures object at the root of Onfido.init(), set useCustomizedApiRequests to true and define the callbacks for onSubmitDocument, onSubmitVideo, onSubmitSelfie.

2 ...
3 enterpriseFeatures: {
4 useCustomizedApiRequests: true,
5 onSubmitDocument: (documentData) => {
6 // Your callback code here
7 },
8 onSubmitSelfie: (selfieData) => {
9 // Your callback code here
10 },
11 onSubmitVideo: (videoData) => {
12 // Your callback code here
13 },
14 },

The callbacks return a FormData object, including the information that the SDK would send to Onfido. The callbacks are invoked when the end user confirms their image through the user interface.

Note that the data can also be returned in json format by adding the property formatter: 'raw' under the enterpriseFeatures object.

onSubmitDocument data parameter
2 file: blob,
3 side: string,
4 type: string,
5 sdk_validations: object,
6 sdk_source: string,
7 sdk_version: string,
8 sdk_metadata: object,
onSubmitSelfie data parameter
2 file: blob,
3 snapshot: blob,
4 sdk_source: string,
5 sdk_version: string,
6 sdk_metadata: object,
onSubmitVideo data parameter
2 file: blob,
3 challenge: { type: 'recite' / 'movement', query: number[] / string }
4 challenge_id: string,
5 challenge_switch_at: number, // seconds
6 languages: { source: 'sdk', language_code: string }
7 sdk_source: string,
8 sdk_version: string,
9 sdk_metadata: object,

Uploading the media files to Onfido

By default, this feature will prevent the request from being sent to Onfido, requiring you to manually upload the media files to Onfido from your backend for further processing. We strongly recommend that you add all of the data provided to you through the callbacks in your request to the appropriate endpoint - /documents or /live_photos. Additionally, you should use the SDK token created for each applicant in the Authorization header of the request as shown below.

Note that the SDK token is not included in the FormData provided by the callbacks. You may want to append this, or a different unique identifier that is mapped to the applicant's SDK token, on your backend before sending it off.

1Authorization: Bearer <SDK token here>

If you wish for the SDK to also upload the user-submitted data directly to Onfido you can resolve the promise with an object containing continueWithOnfidoSubmission: true.

1onSubmitDocument: (data) => {
2 // Your callback code here
3 ...
4 // Once your code has executed, resolve the promise
5 return Promise.resolve({ continueWithOnfidoSubmission: true })
6 }

Managing the Onfido response

Once you have sent the request to Onfido yourself, you can supply the SDK with the response so it can determine what the end user should be presented with. In the case where a success response is received, the promise should be resolved with onfidoSuccessResponse: <onfidoResponse>. Otherwise reject the promise with the Onfido error response. Note: An error response could be returned due to image quality issues. In this case, the SDK will present the end user with the appropriate error message.

1onSubmitDocument: (data) => {
2 // Send request to Onfido API /documents via your backend proxy
3 .then(onfidoSuccessResponse =>
4 Promise.resolve({ onfidoSuccessResponse: <onfidoResponse> }))
5 .catch(onfidoError => Promise.reject(onfidoError))
6 }

This is a sample openAPI YAML file you could use as an example to start your own proxy.

1openapi: 3.0.0
3 title: Network decouple back-end sample
4 description: Network decouple back-end setup skeleton
5 version: '1.0'
6 contact: {}
7tags: []
8servers: []
10 schemas:
11 IDocumentsRequest:
12 type: object
13 properties:
14 file:
15 type: string
16 format: binary
17 description: Uploaded document. Passed in from the web SDK callback.
18 type:
19 type: string
20 default: passport
21 description: >-
22 The type of document that was submitted. Passed in from the web SDK
23 callback.
24 side:
25 type: string
26 default: front
27 description: >-
28 The type side of the document that was submitted. Passed in from the
29 web SDK callback.
30 sdk_metadata:
31 type: object
32 description: >-
33 The metadata that web SDK collects. Forward this to Onfido API
34 without modifications. Passed in from the web SDK callback.
35 sdk_validations:
36 type: object
37 description: >-
38 This is a an object used by web SDK to seek image quality feedback
39 from the API. Forward this object without modifications to Onfido
40 API. Passed in from the web SDK callback.
41 sdk_source:
42 type: string
43 default: onfido_web_sdk
44 description: >-
45 The source of origin of the requests. Forward this without
46 modifications to the Onfido API. Passed in from the web SDK callback.
47 sdk_version:
48 type: string
49 description: >-
50 The SDK version. Forward this without modifications to the Onfido
51 API. Passed in from the web SDK callback.
52 IMultiFrameSelfieRequest:
53 type: object
54 properties:
55 file:
56 type: string
57 format: binary
58 description: Uploaded photo
59 sdk_metadata:
60 type: object
61 description: >-
62 The metadata that web SDK collects. Forward this to Onfido API
63 without modifications. Passed in from the web SDK callback.
64 sdk_source:
65 type: string
66 default: onfido_web_sdk
67 description: >-
68 The source of origin of the requests. Forward this without
69 modifications to the Onfido API. Passed in from the web SDK callback.
70 sdk_version:
71 type: string
72 description: >-
73 The SDK version. Forward this without modifications to the Onfido
74 API. Passed in from the web SDK callback.
75 snapshot:
76 type: string
77 format: binary
78 description: Uploaded snapshot taken by the Web SDK to improve fraud analysis.
80 /onfido/v3.3/documents:
81 post:
82 operationId: OnfidoController documents
83 parameters:
84 - name: Authorization
85 in: header
86 description: Customer back-end Authentication token
87 schema:
88 type: string
89 requestBody:
90 required: true
91 description: The API endpoint to intercept the document upload from the Web SDK
92 content:
93 multipart/form-data:
94 schema:
95 $ref: '#/components/schemas/IDocumentsRequest'
96 responses:
97 '200':
98 description: >-
99 The response received from Onfido v3.3/documents API call. The
100 response format might slightly vary with the use case. Forward it
101 without modifications as the callback response.
102 content:
103 application/json:
104 schema:
105 properties:
106 id:
107 type: string
108 format: uuid
109 created_at:
110 type: string
111 format: date-time
112 file_name:
113 type: string
114 file_size:
115 type: integer
116 file_type:
117 type: string
118 type:
119 type: string
120 side:
121 type: string
122 issuing_country:
123 type: string
124 applicant_id:
125 type: string
126 href:
127 type: string
128 download_href:
129 type: string
130 sdk_warnings:
131 type: object
132 '201':
133 description: ''
134 content:
135 application/json:
136 schema:
137 type: object
138 '422':
139 description: ''
140 content:
141 application/json:
142 schema:
143 properties:
144 error:
145 type: object
146 properties:
147 type:
148 type: string
149 message:
150 type: string
151 fields:
152 type: object
153 /onfido/v3.6/live_photos:
154 post:
155 operationId: OnfidoController
156 parameters:
157 - name: Authorization
158 in: header
159 description: Customer back-end Authentication token
160 schema:
161 type: string
162 requestBody:
163 required: true
164 description: The API endpoint to intercept the live photos upload from the Web SDK
165 content:
166 multipart/form-data:
167 schema:
168 $ref: '#/components/schemas/IMultiFrameSelfieRequest'
169 responses:
170 '200':
171 description: >-
172 The response received from Onfido v3.6/live_photos API call. The
173 response format might slightly vary with the use case. Forward it
174 without modifications as the callback response.
175 content:
176 application/json:
177 schema:
178 properties:
179 id:
180 type: string
181 format: uuid
182 created_at:
183 type: string
184 format: date-time
185 file_name:
186 type: string
187 file_type:
188 type: string
189 file_size:
190 type: integer
191 href:
192 type: string
193 sdk_source:
194 type: string
195 sdk_version:
196 type: string
197 download_href:
198 type: string
199 '201':
200 description: ''
201 content:
202 application/json:
203 schema:
204 type: object

Custom media callbacks in cross-device flows

In the context of cross-device flows, you may choose to enable the media callbacks in either the desktop session or the mobile session.

A prerequisite is that you host the cross-device experience of the Onfido SDK yourself, as described in the self-hosted cross-device URL section of this document.

Enable custom media callbacks in mobile session

Once you have a server with the Onfido Web SDK installed and set up, you must initialize the mobile session with mobileFlow: true in addition to the callbacks and useCustomizedApiRequests options shown above.

2 ...
3 enterpriseFeatures: {
4 useCustomizedApiRequests: true,
5 mobileFlow: true,
6 onSubmitDocument: (documentData) => {
7 // Your callback code here
8 },
9 onSubmitSelfie: (selfieData) => {
10 // Your callback code here
11 },
12 onSubmitVideo: (videoData) => {
13 // Your callback code here
14 },
15 },
Enable custom media callbacks in desktop session

Media callbacks can also be triggered in the desktop session instead of the mobile session. To do so, please contact your Onfido Solution Engineer or Customer Success Manager as additional configuration is required.

User analytics callbacks

The SDK allows you to track a user's journey through the verification process via a dispatched event. This gives insight into how your users make use of the SDK screens.

Overriding the hook

In order to track a user's progress through the SDK an EventListener must be added that listens for UserAnalyticsEvent events. This can be done anywhere within your application.

The code inside of the EventListener callback will be invoked when an event is triggered.

1addEventListener('userAnalyticsEvent', (event) => /*Your code here*/);

The event parameter being passed in the callback contains the following information:

  • eventName {String}: Name of the event triggered (full list below)
  • properties {Object}: Event-specific properties
  • isCrossDevice {Boolean}: Set to true when the event originates from a mobile session


You can access the sdk version through the handle once the SDK is loaded.

1const onfidoOut = Onfido.init({...})
3onfidoOut.addEventListener('userAnalyticsEvent', (event) => {
4 console.log('Version', onfidoOut.version)

Self-hosted cross-device URL

The following feature must be enabled for your account before it can be used. For more information, please contact your Onfido Solution Engineer or Customer Success Manager.

This feature allows you to specify your own custom or whitelabel url that the cross-device flow will redirect to instead of the Onfido default id.onfido.com. To use this feature, generate an SDK token as shown below and use it to start the SDK.

1$ curl https://api.onfido.com/v3/sdk_token \
2 -H 'Authorization: Token token=YOUR_API_TOKEN' \
3 -F 'applicant_id=YOUR_APPLICANT_ID' \
4 -F 'referrer=REFERRER_PATTERN' \
5 -F 'cross_device_url=YOUR_CUSTOM_URL'

In addition to this, you must either:

  • Set up a server to forward the incoming HTTP request, including the path, to https://id.onfido.com

  • Set up a server to host the Onfido Web SDK yourself at the provided URL

Set up a server to forward the incoming HTTP request, including the path, to https://id.onfido.com

You can do this by setting up a server as a reverse proxy so that the URL that the end-user sees is your selected URL but the content shown is the Onfido-hosted Web SDK. An example set-up for a minimal nginx server using docker:


1server {
2 # Change the next 2 lines as needed
3 listen 80;
4 server_name localhost;
6 location / {
7 # This forwards the path to Onfido and is the only change
8 # necessary when working with the default nginx configuration
9 proxy_pass https://id.onfido.com;
10 }


1FROM nginx:1.15.8-alpine
3COPY ./nginx.conf /etc/nginx/conf.d/default.conf

Set up a server to host the Onfido Web SDK yourself at the provided URL

This server must use the same version of the Onfido Web SDK and must initialize the SDK with Onfido.init({ mobileFlow: true }). All other configuration options, except for callbacks provided for the useCustomizedApiRequests feature, will be provided by your original instance of the Onfido Web SDK.

This is an example of how you could host the Onfido Web SDK with minimal setup. This example involves using docker and an nginx image to serve an html file which starts the Onfido Web SDK using just the js and css files from the Onfido CDN (https://sdk.onfido.com/<version>).

File structure for this minimal example:

1- dockerfile
2- nginx.conf
3- index.html


1FROM nginx:1.15.8-alpine
3COPY ./nginx.conf /etc/nginx/conf.d/default.conf
5COPY ./index.html /usr/share/nginx/html/
7COPY ./dist /usr/share/nginx/sdk/


1server {
2 # Change the next 2 lines as needed
3 listen 80;
4 server_name localhost;
6 location ~ ^/[0-9a-zA-Z]+$ {
7 root /usr/share/nginx/html;
8 try_files $uri /index.html =404;
9 }
11 location ~* \.(js|jpg|png|css)$ {
12 root /usr/share/nginx/sdk/;
13 }


1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <meta
5 charset="utf-8"
6 name="viewport"
7 content="width=device-width, initial-scale=1"
8 />
9 <meta name="mobile-web-app-capable" content="yes" />
10 <meta name="apple-mobile-web-app-capable" content="yes" />
11 <meta name="format-detection" content="telephone=no" />
12 <title>Onfido Verification</title>
13 <style type="text/css">
14 html,
15 body {
16 height: 100%;
17 margin: 0;
18 }
19 body,
20 button {
21 -webkit-font-smoothing: antialiased;
22 }
23 @media (min-width: 30em) {
24 #onfido-mount {
25 position: relative;
26 top: 10%;
27 }
28 .onfido-sdk-ui-Modal-inner {
29 font-family: 'Open Sans', sans-serif !important;
30 }
31 }
32 </style>
33 <script type="text/javascript">
34 // commonjs style require
35 var Onfido = require('onfido-sdk-ui')
37 var version = window.location.pathname.substring(1, 3)
39 var script = document.createElement('script')
40 script.onload = function () {
41 window.onfidoOut = Onfido.init({ mobileFlow: true })
42 }
43 document.head.appendChild(script)
44 </script>
45 </head>
47 <body>
48 <div id="onfido-mount"></div>
49 </body>

More information

Supported browsers

Latest ✔Latest ✔Latest ✔Latest ✔

Node.js supported versions

The SDK is compatible with the all supported Node.js versions (currently starting with Node.js 16).


The Onfido SDK has been optimized to provide the following accessibility support by default:

  • Screen reader support: accessible labels for textual and non-textual elements available to aid screen reader navigation, including dynamic alerts
  • Keyboard navigation: all interactive elements are reachable using a keyboard
  • Sufficient color contrast: default colors have been tested to meet the recommended level of contrast
  • Sufficient touch target size: all interactive elements have been designed to meet the recommended touch target size

Refer to our accessibility statement for more details.

⚠️ Note: If you make your own UI customizations, you are responsible for ensuring that the UI changes will still adhere to accessibility standards. For example, accessible color contrast ratios and dyslexic friendly fonts.


General Content Security Policy (CSP)

For guide on CSP common issue and recommendations, please refer to the guide Onfido Web SDKn and Content Security Policy (CSP) guide.

Iframe integration

For instruction and guide on how to embed the Onfido Web SDK in an iFrame, please refer to the guide Using the Onfido web SDK in an iFrame.

Upload fallback

Onfido Web SDK versions <13.0.0 had a parameter named uploadFallback that could be set on both the document step and the face step. This parameter allowed clients to present end-users with a file input capability during the SDK flow.

With Web SDK 14.15 and above, the uploadFallback client-side parameter has been reintroduced. To enhance the overall flow security, it is disabled by default and requires activation through the Onfido Support Team.

Permissions issues when using the Web SDK in a webview

For recommendations and code samples on how to embed the Onfido Web SDK in a webview, please refer to the guide Using the Onfido web SDK in a webview.


Should you encounter any technical issues during integration, please contact Onfido's Customer Support team via email, including the word ISSUE: at the start of the subject line.

Alternatively, you can search the support documentation available via the customer experience portal, public.support.onfido.com.

We recommend you update your SDK to the latest version release as frequently as possible. Customers on newer versions of the Onfido SDK consistently see better performance across user onboarding and fraud mitigation, so we strongly advise keeping your SDK integration up-to-date.

You can review our full SDK versioning policy here.

License Information

Please see LICENSE for licensing details.