captionbob docs

Version 1.0.0
Contents ↓

HTTP API examples

Get the effects

An effect draws the captions. The HTTP API calls an effect a style. This page lists the effects and finds one effect by its name.

Before you start

Put your API key in place of <your API key>. The Quickstart shows how to make a key.

CAPTIONBOB_URL is the default address of the server. Change it when your server listens on another host or port. The code of each step runs after this first code. The curl code runs in bash and reads values from the answers with jq. The Python code uses the package requests. The JavaScript code runs in Node.js 22 or later as an ES module, such as a file example.mjs.

The answers on this page are real answers of a captionbob server, recorded on 2026-10-28. Your ids, names and times are different.

curl

CAPTIONBOB_URL="http://127.0.0.1:9400"
CAPTIONBOB_KEY="<your API key>"

Python

import requests

CAPTIONBOB_URL = "http://127.0.0.1:9400"
HEADERS = {"Authorization": "Bearer <your API key>"}

JavaScript

const CAPTIONBOB_URL = "http://127.0.0.1:9400";
const HEADERS = { Authorization: "Bearer <your API key>" };
let response;
let answer;

Step 1: List the effects

Each effect has its name, has_emoji_layers and its settings. Each setting has its name, its type and its default value.

curl

ANSWER=$(curl -s "$CAPTIONBOB_URL/api/styles" \
  -H "Authorization: Bearer $CAPTIONBOB_KEY")
echo "$ANSWER"
STYLES=$(echo "$ANSWER" | jq -r '.styles')

Python

response = requests.get(
    f"{CAPTIONBOB_URL}/api/styles",
    headers=HEADERS,
)
if not response.ok:
    raise RuntimeError(response.text)
answer = response.json()
print(answer)
styles = answer["styles"]

JavaScript

response = await fetch(`${CAPTIONBOB_URL}/api/styles`, { headers: HEADERS });
if (!response.ok) {
  throw new Error(await response.text());
}
answer = await response.json();
console.log(JSON.stringify(answer, null, 2));
const styles = answer.styles;

Answer: status 200.

{
  "styles": [
    {
      "name": "word_by_word",
      "has_emoji_layers": false,
      "settings": [
        {
          "name": "most_words",
          "type": "integer",
          "default": 3
        },
        {
          "name": "fewest_words",
          "type": "integer",
          "default": 1
        },
        {
          "name": "font_name",
          "type": "string",
          "default": "DejaVu Sans"
        },
        {
          "name": "font_size",
          "type": "integer",
          "default": 80
        },
        {
          "name": "bold",
          "type": "boolean",
          "default": true
        },
        {
          "name": "primary_color",
          "type": "string",
          "default": "#FFFFFF"
        },
        {
          "name": "stroke_color",
          "type": "string",
          "default": "#000000"
        },
        {
          "name": "stroke_width",
          "type": "number",
          "default": 6
        },
        {
          "name": "bottom_position",
          "type": "number",
          "default": 0.75
        },
        {
          "name": "side_margin",
          "type": "integer",
          "default": 54
        },
        {
          "name": "fade_seconds",
          "type": "number",
          "default": 0.1
        },
        {
          "name": "hold_seconds",
          "type": "number",
          "default": 0.6
        }
      ]
    }
  ]
}

The answer has 71 effects. This page shows the first 1.

Step 2: Find the effect bouncy_emoji

The API has no route for one effect. Find the effect in the list by its name.

curl

STYLE=$(echo "$STYLES" | jq '.[] | select(.name == "bouncy_emoji")')
echo "$STYLE"

Python

style = None
for item in styles:
    if item["name"] == "bouncy_emoji":
        style = item
        break
print(style)

JavaScript

const style = styles.find((item) => item.name === "bouncy_emoji");
console.log(JSON.stringify(style, null, 2));

Result:

{
  "name": "bouncy_emoji",
  "has_emoji_layers": true,
  "settings": [
    {
      "name": "most_words",
      "type": "integer",
      "default": 6
    },
    {
      "name": "fewest_words",
      "type": "integer",
      "default": 1
    },
    {
      "name": "font_name",
      "type": "string",
      "default": "DejaVu Sans"
    },
    {
      "name": "font_size",
      "type": "integer",
      "default": 80
    },
    {
      "name": "bold",
      "type": "boolean",
      "default": true
    },
    {
      "name": "primary_color",
      "type": "string",
      "default": "#FF1911"
    },
    {
      "name": "stroke_color",
      "type": "string",
      "default": "#000000"
    },
    {
      "name": "stroke_width",
      "type": "number",
      "default": 6
    },
    {
      "name": "bottom_position",
      "type": "number",
      "default": 0.75
    },
    {
      "name": "side_margin",
      "type": "integer",
      "default": 54
    },
    {
      "name": "words_per_line",
      "type": "integer",
      "default": 3
    },
    {
      "name": "secondary_color",
      "type": "string",
      "default": "#FFE434"
    },
    {
      "name": "tertiary_color",
      "type": "string",
      "default": "#FF1911"
    },
    {
      "name": "tilt_degrees",
      "type": "number",
      "default": 5
    },
    {
      "name": "start_scale",
      "type": "number",
      "default": 0.8
    },
    {
      "name": "grow_seconds",
      "type": "number",
      "default": 0.5
    },
    {
      "name": "emoji_width_part",
      "type": "number",
      "default": 0.2
    },
    {
      "name": "emoji_gap",
      "type": "number",
      "default": 20
    },
    {
      "name": "hold_seconds",
      "type": "number",
      "default": 0.6
    }
  ]
}