Developer guideBrand look

Brand look

Accent colour, corner radius, light or dark and the optional trust line, set per site, and how the box behaves on phones and with a keyboard.

Four settings per site

The look is set on our side, per site key, and sent to the loader with every challenge. Nothing changes in your page, and a change on our side reaches every visitor on their next check. Send us the values for your site; a self-hosted service sets them itself.

SettingValuesDefaultNote
accent#RRGGBB#1746D1The hold button border and text, the fill, the puzzle handle and the focus rings. Refused when its contrast against the box it will appear on is under 3:1, because the accent is used as text. A tint of it, at 25% opacity, becomes the hold's fill.
radiuswhole number, 0 to 2412Corner radius of the box in pixels. Buttons and the picture use two thirds of it.
modeauto, light, darkautoauto follows the visitor's system setting. light or dark fixes the palette to match a page that is always one or the other.
trusttrue, falsefalseOff by default. Set it to true per site to show the "Protected by OTCaptcha" line under the box. It is plain text, never a link, so it can never take a visitor out of your form.
JSON
// The look travels with the challenge, beside it, so a box that opens always has it.
{
  "status": "success",
  "data": { …the challenge… },
  "theme": { "accent": "#D60082", "radius": 6, "mode": "light", "trust": false }
}

The loader checks the values again before using them and drops anything outside these forms, since they reach CSS. They are applied as CSS custom properties on the box, never as text in a stylesheet. A box only ever opens after a successful challenge request, so a box never appears without its look; the offline path shows no box at all.

Environment
# A self-hosted service: one JSON object keyed by site key. A bad value stops the start.
OTCAPTCHA_THEMES='{"[SITE KEY]":{"accent":"#D60082","radius":6,"mode":"light","trust":false}}'

The two palettes

RoleLightDark
Box background#FFFFFF#16213A
Text#0F1B33#EEF2FA
Secondary text#47536B#A9B4C8
Lines#D5DDEC#33415E
Accent, when none is set#1746D1#9DB6FF
Verified#0B6B45#6FD8AE

An accent you set replaces the accent in both palettes, which is why the contrast check runs against the background the box will have. The backdrop behind the box is a translucent dark blue with a slight blur, in both modes.

What cannot be changed, and why

  • Layout and text. The box is 348 px wide at most, centred, with a title, the control, a status line and, when a site turns it on, the trust line. On screens up to 480 px wide it becomes a sheet that rises from the bottom, within reach of a thumb, with room for the device's safe area. The wording is fixed per language so that instructions tested with real visitors stay tested.
  • Typeface. The system font stack, so nothing is downloaded and the box looks native on every platform.
  • Motion. A fade and rise on open, a soft pulse on the hold button, a shake on a missed slide, a tick on success and a short vibration where the device supports it. All of it is skipped when the visitor has asked for reduced motion.
  • Keyboard and focus. The box is a dialog: Tab stays inside it, Escape closes it, and focus returns to where it was when it ends, unless your page has moved focus itself in the meantime. The hold works with the space bar or Enter; the puzzle piece moves with the arrow keys and Enter submits.
  • Z-order. The box sits above everything on the page. A page element with a higher stacking order would hide a check the visitor must complete.

Languages

The box speaks English, Spanish, Portuguese, Arabic, Hindi and Chinese, chosen by the language you pass to init. Arabic lays the box out right to left; the puzzle slider itself keeps left to right, so the piece follows the hand. Any other language, or none, gives English. The strings cover the title, the instructions for the hold and the slide, the early-release message, the miss message, "Use a different check", "Verified", "Close" and the trust line.