Skip to content

Widget API

The Widget API is installed by the api.js we provide at /public/api.js of your designed hostname (eg https://global.captcha.party/public/api.js).

Install the API script

To load the API, you need to add it as a script eleement.

For example, you can include this script tag in your <head> element:

<script src="https://global.captcha.party/public/api.js" async defer></script>

You can also load the API dynamically with Javascript:

const script = document.createElement("script");
script.src = "https://global.captcha.party/public/api.js";
script.defer = true;
script.async = true;
document.head.appendChild(script);

API ready

The API is not immediately available because the browser has to fetch the script first, parse it, and execute it which means your scripts may run before the API is ready and installed.

You can check if the API is installed by confirming the presence of window.pcaptcha.

To get notified when the API is ready, you can use one of the following methods:

Event listeners

You can use Javascript to add an event listener for the load event. We recommend this approach because it allows you to also listen to the error in case the script fails to load and correctly handle that scenario (this could happen if you don’t have the correct CSP, an extension is blocking the script, network failure, an outage on our end etc).

const script = document.createElement("script");
script.src = "https://global.captcha.party/public/api.js";
script.defer = true;
script.async = true;
script.addEventListener("load", () => {
window.pcaptcha.render(...);
});
script.addEventListener("error", () => {
// handle missing captcha, eg: show an error and disable forms
});
document.head.appendChild(script);

Callbacks

Another way to get notified are callbacks. This is discouraged because it’ll not notify you of errors and it’s not very flexible.

There are 3 ways to declare a callback using the script element (they all have the same effect):

  • using the onload query parameter (.../api.js?onload=callback)
  • using the onload hash parameter (.../api.js#onload=callback)
  • using the data-onload attribute (<script data-onload="callback">)

Make sure the callback is declared before the script element.

<script
src="https://global.captcha.party/public/api.js?onload=onCaptchaLoad"
async
defer
></script>
<script>
// always loaded earlier thanks to `defer` on the script element
function onCaptchaLoad() {
window.pcaptcha.render(...);
}
</script>

Additionally, you can also set window.pcaptcha_callback to a callback function.

<script src="https://global.captcha.party/public/api.js" async defer></script>
<script>
// always loaded earlier thanks to `defer` on the script element
window.pcaptcha_callback = () => {
window.pcatcha.render(...);
}
</script>

Content Security Policy

The Widget API is CSP3 nonce compatible. Make sure to add the nonce to the script element:

<script src="" async defer nonce="..."></script>

If you aren’t using a nonce, you need to add the following CSP directives:

  • script-src: https://global.captcha.party/
  • frame-src: https://global.captcha.party/

We recommend evaluating your CSP using Google’s CSP Evaluator.

pcaptcha API

Documentation for the functions exposed by api.js.

pcaptcha.render

pcaptcha.render(challengeParameters): string

This function takes a challenge parameters object and returns a widget id that can be used to execute, reset or remove it.

Challenge Parameters

KeyTypeRequired Description
sitekeystringyessitekey
executionChallengeExecutionnoone of auto (default), immediately, form-focus, manual or execute
refreshChallengeRefreshnoone of auto (default), manual or never
datastringnocustom string that is returned in /siteverify (requires Professional plan)
actionstringnocustom string that is used to differentiate widgets in analytics (requires Business plan)
containerHTMLElementnothe container of the challenge
modalbooleannoif the challenge will be rendered as modal, forced to true if no container is set
formHTMLFormElement or stringnoassociated form element, if not set, the dom will be traversed upwards from the container instead for the nearest form element
formSubmitDisablebooleannoif set to true, the form will not be submittable until the CAPTCHA is solved
tabIndexnumbernotabindex of the widget
responseFieldNamestringnoname of the hidden input element, defaults to p-captcha-solution
languagestringnolanguage of the widget
colorsChallengeColorsnocustom branding colors (requires Enterprise plan)
themestringnotheme of the widget
onSuccessfunctionnocallback that will be called with the solution
onExpirefunctionnocallback that will be called when the solution expires
onErrorfunctionnocallback that will be called on error
onFailfunctionnocallback that will be called when automation software is detected

Challenge Execution

The execution parameter controls when the challenge is executed.

  • immediately: the challenge runs immediately as soon as it’s loaded
  • form-focus: the user has to either click a button or focus the form the widget is in
  • manual: the user has to click a button
  • execute: runs once you call pcaptcha.execute
  • auto: it depends

Auto logic:

  • if it’s a modal and has a container -> execute
  • if it’s a modal and has no container -> immediately
  • if it’s in a form -> form-focus
  • else -> manual

Challenge Refresh

The refresh parameter controls how the widget behaves once the solution expires (and the onExpire callback is called).

  • auto: the challenge is reloaded and runs again
  • manual: the user is told the solution expired and has to click a button to reload it
  • never: the user is not informed and the challenge does not reload. The onExpire callback is still called, and you can still reset it

pcaptcha.reset

pcaptcha.reset(widgetId): void

Reloads the widget and does not return anything.

It is not necessary to execute it again.

pcaptcha.remove

pcaptcha.remove(widgetId): void

Removes the widget from the DOM and aborts execution. This also includes the associated <input> element.

pcaptcha.execute

pcaptcha.execute(widgetId): void

Has no effect when the widget is using execution="immediately".

  • When using execution="execute" the widget will become visible after calling this function.
  • When using execution="manual" the button is skipped.
  • When using execution="form-focus" the button is skipped.

pcaptcha.update

pcaptcha.update(widgetId, callbacks): void

Updates the callbacks used by the Widget.

pcaptcha.hide

pcaptcha.hide(widgetId): void

Hides the widget, the widget needs to be reset to re-appear. This is mainly useful for modals where the <input> element is still required, so it can’t be removed.

pcaptcha.getSolution

pcaptcha.getSolution(widgetId): string | null

Get the widget’s solution, returns undefined/null if the widget expired or has not been solved yet.

pcaptcha.supportedLanguages

const pcaptcha.supportedLanguages: Array<string>

A list of all currently supported languages.

Widget Events

During execution, the widget may emit certain events that can be listened to. These events are:

  • success: the widget has been solved
  • expire: the solution has expired
  • error: an error occured
  • fail: automation software has been detected

Callbacks

You can listen to these events by adding a callback when calling pcaptcha.render or by using the pcaptcha.update function or using the data- attributes.

const container = document.getElementById("container");
window.pcaptcha.render({
sitekey: "your-sitekey",
container,
onSuccess: (solution) => console.log("solved", solution),
onError: (error) => console.log("error", error),
});

Event listeners

You can also listen to these events by adding an event listener to the container element.

const container = document.getElementById("container");
window.pcaptcha.render({
sitekey: "your-sitekey",
container,
});
container.addEventListener("pcaptcha-success", (event) => {
console.log("solved", event.detail);
});

HTML Rendering

HTML Rendering works by finding all elements with the p-captcha class and then creating an Challenge Parameters object from the data- attributes and then calls the pcaptcha.render function.

During the attribute conversion, some fields are renamed:

  • data-tab-index -> tabIndex
  • data-response-field-name -> responseFieldName

And also callbacks are handled differently due to HTML using strings:

  • data-success-callback -> onSuccess
  • data-expire-callback -> onExpire
  • data-error-callback -> onError
  • data-fail-callback -> onFail

Function name lookup is lazy and delayed until the callback is actually called.

// lazy:
onSuccess = (solution) => window[name]?.(solution);
// immediate:
onSuccess = window[name];

Finally, the data-colors attribute is JSON-decoded and renamed to colors.

HTML Form

If no form parameter is set, the parents of the container parameter are checked for a form instead.

If a form is found, it will have priority over the container for the <input> element.

If formSubmitDisable is set, the form will also not be submittable until the CAPTCHA is solved.

Challenge errors

The widget may call onError due to various reasons with one of the following error codes:

Error CodeDescription
failautomation software detected
iframe_load_errorthe iframe failed to load
invalid_sitekeyan invalid sitekey was passed
invalid_hostnamean invalid hostname was used to load the iframe
limits_exceeededusage limit has been exceeded for this sitekey
direct_accessthe iframe was visited directly
browser_not_supportedthe browser is not supported
client_execution_errora fatal error occured while running the challenge
client_ratelimitedthe client is being ratelimited
errora fatal error occured
network_errora network error occured while running the challenge
unknown_errorsomething went wrong, but we don’t know what