Text & strings

String Case

Convert between camel, snake, kebab, pascal, constant, title, and related cases. Input case is auto-detected. Use to=all to fetch all variants at once.

MCP tool: text.convert_string_case

GET /v1/string/case

Parameters:

ParameterTypeRequiredDescription
textstringString to convert
tostringcamel / snake / kebab / pascal / constant / title / lower / upper / all

Request example:

curl "https://api.thousand-api.com/v1/string/case?text=hello_world_foo&to=camel" \
  -H "x-api-key: YOUR_API_KEY"

Response example:

{
  "text": "hello_world_foo",
  "to": "camel",
  "detected_case": "snake",
  "result": "helloWorldFoo"
}

Response:

When to=all, result is an object keyed by case name. For strings containing non-ASCII characters (e.g. Japanese), only lower and upper are transformed; other cases return the input unchanged.

Random String

Generates cryptographically secure random strings. Configurable charset, length, and count. Uses Node.js built-in crypto.

MCP tool: text.generate_random_string

GET /v1/random/string

Parameters:

ParameterTypeRequiredDescription
lengthinteger-String length (default: 16, max: 128)
charsetstring-alphanumeric / alphabetic / numeric / hex / urlsafe / uppercase
countinteger-Number of strings to generate (default: 1, max: 10)

Request example:

curl "https://api.thousand-api.com/v1/random/string?length=8&charset=uppercase&count=3" \
  -H "x-api-key: YOUR_API_KEY"

Response example:

{
  "length": 8,
  "charset": "uppercase",
  "count": 3,
  "results": ["AB3K7MN2", "PQ9XL4WZ", "R7MN2PQ9"]
}

Response:

Generated strings are suitable for session tokens, temporary passwords, and invite codes. For production cryptographic keys, use purpose-appropriate key generation (e.g. crypto.generateKeyPair).

Text Stats

Extract plain text from HTML, return text statistics and approximate token counts, split long text into sentence/paragraph-aware chunks, mask PII (email, Japanese phone numbers, credit cards), compute line-based diffs and similarity scores, or generate URL-safe slugs from human-readable titles.

MCP tools: text.extract_text_from_html, text.get_text_stats, text.estimate_tokens, text.split_text, text.mask_pii, text.diff_text, text.diff_markdown_tables, text.calc_text_similarity, text.generate_slug

POST /v1/text/html-to-text

Parameters:

ParameterTypeRequiredDescription
htmlstringHTML text to extract (max 1MB)
max_lengthinteger-Optional maximum character count for output (positive integer)
preserve_linksboolean-When true, return a list of { text, href } links (default false)

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/html-to-text" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<h1>Hello</h1><p>Visit <a href=\"https://example.com\">Example</a></p>",
    "max_length": 500,
    "preserve_links": true
  }'

Response example:

{
  "text": "Hello\n\nVisit Example",
  "char_count": 19,
  "truncated": false,
  "links": [
    {
      "text": "Example",
      "href": "https://example.com"
    }
  ]
}

Response fields:

ParameterDescription
textPlain text with tags removed, entities decoded, and whitespace normalized
char_countCharacter count of text
truncatedTrue when max_length truncated the output
linksPresent only when preserve_links is true; array of { text, href }

Response:

script and style tags (including their contents) are removed entirely. Block elements (p, div, h1–h6, li, etc.) become line breaks; three or more consecutive newlines are compressed to two. Useful for reducing tokens from HTML fetched via the Scraper tool.

POST /v1/text/stats

Parameters:

ParameterTypeRequiredDescription
textstringText to analyze (max 100KB)
langstring-Language code (ja / en, default en)

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/stats" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "AI agents need reliable MCP utilities.",
    "lang": "en"
  }'

Response example:

{
  "characters": 42,
  "characters_no_spaces": 37,
  "words": 7,
  "sentences": 1,
  "paragraphs": 1,
  "reading_time_seconds": 2
}

Response fields:

ParameterDescription
charactersTotal character count (includes spaces and newlines)
characters_no_spacesCharacter count excluding spaces, tabs, and newlines
wordsWord count (ja: non-whitespace characters; en: space-separated tokens)
sentencesSentence count (ja: 。!?; en: .!?)
paragraphsParagraph count (split on blank lines)
reading_time_secondsEstimated reading time in seconds (rounded up)

Response:

Reading speed: ja uses 500 characters/min (characters_no_spaces); en uses 225 words/min (words). No external APIs required.

POST /v1/text/estimate-tokens

Parameters:

ParameterTypeRequiredDescription
textstringText to estimate token count for (max 1MB)
model_hintstring-Model hint (claude / gpt / generic, default generic)

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/estimate-tokens" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Check token usage before sending long HTML or documents to an LLM.",
    "model_hint": "generic"
  }'

Response example:

{
  "char_count": 62,
  "estimated_tokens": 16,
  "model_hint": "generic",
  "method": "approximation",
  "breakdown": {
    "ascii_chars": 58,
    "japanese_chars": 0,
    "other_chars": 4
  },
  "note": "This is an approximation. Actual token count may vary by ±15%."
}

Response fields:

ParameterDescription
char_countTotal character count
estimated_tokensApproximate token count (rounded up)
model_hintModel hint used for the estimate
methodAlways approximation
breakdown.ascii_charsASCII alphanumeric character count
breakdown.japanese_charsHiragana, katakana, and kanji character count
breakdown.other_charsSymbols, spaces, newlines, and other characters
noteDisclaimer that the result is approximate (±15%)

Response:

Ideal for saving tokens—check consumption before passing HTML or long documents to an LLM. No external libraries (e.g. tiktoken).

POST /v1/text/split

Parameters:

ParameterTypeRequiredDescription
textstringText to split into chunks (max 1MB). An empty string returns chunk_count: 0
max_charsintegerMaximum characters per chunk, counted in Unicode code points (integer >= 1)
overlapinteger-Characters repeated from the end of the previous chunk (0 <= overlap < max_chars, default 0)
boundarystring-Split unit (sentence / paragraph / char, default sentence). Oversized units fall back to finer boundaries (paragraph → sentence → char)

Example 1: boundary "sentence" (sentence boundaries, default)

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/split" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "First sentence. Second one! Third?",
    "max_chars": 20,
    "boundary": "sentence"
  }'

Response example:

{
  "chunk_count": 2,
  "chunks": [
    { "index": 0, "text": "First sentence. ", "char_count": 16 },
    { "index": 1, "text": "Second one! Third?", "char_count": 18 }
  ]
}

Example 2: boundary "paragraph" (blank-line separated)

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/split" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Intro paragraph.\n\nMain body text here.\n\nSummary.",
    "max_chars": 25,
    "boundary": "paragraph"
  }'

Response example:

{
  "chunk_count": 3,
  "chunks": [
    { "index": 0, "text": "Intro paragraph.\n\n", "char_count": 18 },
    { "index": 1, "text": "Main body text here.\n\n", "char_count": 22 },
    { "index": 2, "text": "Summary.", "char_count": 8 }
  ]
}

Example 3: boundary "char" (fixed-size slices)

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/split" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "abcdefghij",
    "max_chars": 4,
    "boundary": "char"
  }'

Response example:

{
  "chunk_count": 3,
  "chunks": [
    { "index": 0, "text": "abcd", "char_count": 4 },
    { "index": 1, "text": "efgh", "char_count": 4 },
    { "index": 2, "text": "ij", "char_count": 2 }
  ]
}

Example 4: overlap to preserve context between chunks (for RAG)

For RAG chunking, set overlap so each chunk starts with the tail of the previous chunk. This prevents context loss when a single chunk is retrieved by vector search.

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/split" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "The quick brown fox. Jumps over the dog.",
    "max_chars": 25,
    "overlap": 5,
    "boundary": "sentence"
  }'

Response example:

{
  "chunk_count": 2,
  "chunks": [
    { "index": 0, "text": "The quick brown fox. ", "char_count": 21 },
    { "index": 1, "text": "fox. Jumps over the dog.", "char_count": 24 }
  ]
}

Response fields:

ParameterDescription
chunk_countNumber of chunks
chunks[].indexZero-based chunk index
chunks[].textChunk text
chunks[].char_countCharacter count in Unicode code points (an emoji counts as 1)

Response:

Use it to fit long text into LLM context windows, to pre-process documents for RAG chunking, or to split text for summarization/translation while preserving sentence and paragraph meaning. Combine with text.estimate_tokens to size chunks by token budget (character-based sizing only for now). MCP tool: text.split_text

POST /v1/text/mask-pii

Parameters:

ParameterTypeRequiredDescription
textstringText to scan and mask (max 50,000 characters)
typesstring[]-PII types to detect (email / phone_jp / credit_card). Defaults to all when omitted
mask_charstring-Single character used for masking (default *. Surrogate pairs are not allowed)

Masking format (fixed)

ParameterDescription
email****@****.{TLD} (local part and first domain label are always 4 mask chars regardless of length; intermediate subdomains are dropped, only the TLD remains. Example: taro.yamada@mail.example.co.jp → ****@****.jp). Fixed length is intentional so masked output does not leak the original length
phone_jpKeep the leading block and last 4 digits; replace the middle with **** (always 4 chars). Examples: 090-1234-5678 → 090-****-5678, 03-1234-5678 → 03-****-5678
credit_cardCandidates of 13–19 digits are Luhn-validated; only valid cards are masked. Separators are preserved and only the last 4 digits remain. Example: 4111-1111-1111-1111 → ****-****-****-1111

Example 1: Email and phone masking

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/mask-pii" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Contact: taro.yamada@mail.example.co.jp / TEL: 090-1234-5678"
  }'

Response example:

{
  "masked_text": "Contact: ****@****.jp / TEL: 090-****-5678",
  "detected": [
    { "type": "email", "count": 1 },
    { "type": "phone_jp", "count": 1 }
  ]
}

Example 2: Credit cards (Luhn-valid only)

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/mask-pii" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "CARD: 4111-1111-1111-1111 / INVALID: 4111-1111-1111-1112",
    "types": ["credit_card"]
  }'

Response example:

{
  "masked_text": "CARD: ****-****-****-1111 / INVALID: 4111-1111-1111-1112",
  "detected": [
    { "type": "credit_card", "count": 1 }
  ]
}

Response fields:

ParameterDescription
masked_textText after PII masking
detectedPer-type detection counts (types with count 0 are omitted)
detected[].typeemail / phone_jp / credit_card
detected[].countNumber of matches masked for that type

Response:

Processing order is email → credit_card → phone_jp (to avoid treating card digit runs as phone numbers). No external APIs. MCP tool: text.mask_pii

POST /v1/text/diff

Parameters:

ParameterTypeRequiredDescription
originalstringOriginal text to compare (max 256KB)
modifiedstringModified text to compare against (max 256KB)
context_linesinteger-Context lines around changes (0–10, default 3)
formatstring-Output format (unified / json, default unified)

Example: format "unified" (unified diff string)

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/diff" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "original": "line1\nline2\nline3\n",
    "modified": "line1\nline3\nline4\n",
    "context_lines": 3,
    "format": "unified"
  }'

Response example:

{
  "diff": "===================================================================\n@@ -1,3 +1,3 @@\n line1\n-line2\n line3\n+line4\n",
  "added_lines": 1,
  "removed_lines": 1,
  "has_changes": true
}

Example: format "json" (structured chunks)

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/diff" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "original": "alpha\nbeta\n",
    "modified": "alpha\ngamma\n",
    "format": "json"
  }'

Response example:

{
  "diff": [
    { "type": "unchanged", "lines": ["alpha"] },
    { "type": "removed", "lines": ["beta"] },
    { "type": "added", "lines": ["gamma"] }
  ],
  "added_lines": 1,
  "removed_lines": 1,
  "has_changes": true
}

Response fields:

ParameterDescription
diffUnified diff string when format is unified (--- / +++ header lines removed), or an array of { type, lines } when format is json
added_linesNumber of lines added
removed_linesNumber of lines removed
has_changesTrue when any line was added or removed

Response:

Line-based diff. Useful for code review, comparing AI-generated text to the original, and summarizing document revisions. MCP tool: text.diff_text

POST /v1/text/diff-table

Parameters:

ParameterTypeRequiredDescription
beforestringOriginal Markdown table string (max 100KB)
afterstringModified Markdown table string (max 100KB)
key_columnstring | number-Column name or zero-based index used as row identity key. When omitted, the first column name from the before table is used; rows are matched by cell values in that column. For numeric index, the column name at that index in before or after headers is resolved. Specify explicitly when column names differ between tables.

Example 1: DB schema change detection (key_column: "ID")

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/diff-table" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "before": "| ID | 名前 | 型 |\n|---|---|---|\n| 1 | id | bigint |\n| 2 | name | int |\n| 3 | email | varchar(255) |",
    "after": "| ID | 名前 | 型 | NULL許容 |\n|---|---|---|---|\n| 1 | id | bigint | NO |\n| 2 | name | bigint | NO |\n| 4 | created_at | datetime | NO |",
    "key_column": "ID"
  }'

Response example:

{
  "headers": {
    "before": ["ID", "名前", "型"],
    "after": ["ID", "名前", "型", "NULL許容"]
  },
  "added_columns": ["NULL許容"],
  "removed_columns": [],
  "rows": {
    "added": [{ "ID": "4", "名前": "created_at", "型": "datetime", "NULL許容": "NO" }],
    "removed": [{ "ID": "3", "名前": "email", "型": "varchar(255)" }],
    "changed": [{
      "key": "2",
      "changes": [{ "column": "型", "before": "int", "after": "bigint" }]
    }],
    "unchanged_count": 1
  },
  "has_changes": true
}

Example 2: key_column omitted (first column ID as key; non-key header rename only)

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/diff-table" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "before": "| ID | Label |\n|---|---|\n| 1 | alpha |\n| 2 | beta |",
    "after": "| ID | Name |\n|---|---|\n| 1 | alpha |\n| 2 | gamma |"
  }'

Response example:

{
  "headers": {
    "before": ["ID", "Label"],
    "after": ["ID", "Name"]
  },
  "added_columns": ["Name"],
  "removed_columns": ["Label"],
  "rows": {
    "added": [],
    "removed": [],
    "changed": [],
    "unchanged_count": 2
  },
  "has_changes": true
}

Response fields:

ParameterDescription
headers.before / headers.afterColumn header arrays for each table
added_columnsColumn names present only in after
removed_columnsColumn names present only in before
rows.addedRows present only in after (no matching key in before)
rows.removedRows present only in before
rows.changedRows in both tables with differing values in common columns. key is the key-column value; changes is an array of { column, before, after }
rows.unchanged_countRows with matching keys and identical values in all common columns
has_changesTrue when columns were added/removed, rows were added/removed, or any cell changed

text.diff_text compares Markdown tables as plain line-level text (pipe and cell boundary edits appear as line diffs). This API parses GFM tables and returns structured column, row, and cell-level changes. Use text.diff_markdown_tables for DB schemas and spec tables; use text.diff_text for prose and full document diffs.

Response:

Structured diff for GFM Markdown tables. Useful for DB schema and design doc reviews. MCP tool: text.diff_markdown_tables

POST /v1/text/similarity

Parameters:

ParameterTypeRequiredDescription
text1stringFirst text to compare (max 10,000 characters)
text2stringSecond text to compare against (max 10,000 characters)
algorithmsstring[]-Algorithms to run (levenshtein / jaro_winkler / jaccard; default: all three)

Response fields:

ParameterDescription
levenshteinCharacter-level edit distance. Best for typos and misspellings
jaro_winklerEmphasizes prefix matches. Best for names and company deduplication
jaccardToken-set overlap ratio. Best for document content similarity

Example 1: Company name matching

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/similarity" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text1": "株式会社千代田",
    "text2": "(株)千代田"
  }'

Response example:

{
  "text1_length": 7,
  "text2_length": 6,
  "levenshtein": { "distance": 4, "similarity": 0.4286 },
  "jaro_winkler": { "similarity": 0.746 },
  "jaccard": { "similarity": 0.2222 }
}

Example 2: Document duplicate check

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/similarity" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text1": "AIエージェントに確実性を与えるMCPサーバー。リアルタイムデータと副作用を扱います。",
    "text2": "AIエージェントに確実性を与えるMCPサーバー。為替・祝日などのリアルタイムデータを扱います。"
  }'

Response example:

{
  "text1_length": 43,
  "text2_length": 47,
  "levenshtein": { "distance": 12, "similarity": 0.7447 },
  "jaro_winkler": { "similarity": 0.9474 },
  "jaccard": { "similarity": 0.3333 }
}

Response fields:

ParameterDescription
text1_lengthCharacter length of text1
text2_lengthCharacter length of text2
levenshtein.distanceEdit distance (number of operations)
levenshtein.similaritySimilarity score from 0 to 1 (4 decimal places)
jaro_winkler.similarityJaro-Winkler similarity from 0 to 1 (4 decimal places)
jaccard.similarityJaccard coefficient from 0 to 1 (4 decimal places)

text.diff_text returns where texts differ (line-based diff). This API returns how similar they are as numeric scores. Use text.calc_text_similarity for duplicate detection and threshold matching; use text.diff_text to inspect changed sections. Combining both gives similarity and change locations.

Response:

No external APIs. Deterministic: the same input always yields the same result. MCP tool: text.calc_text_similarity

POST /v1/text/slugify

Parameters:

ParameterTypeRequiredDescription
textstringText to slugify (max 1000 characters)
localestring-ja (default): romanize Japanese with Hepburn before slugify; en and others: skip romanization
separatorstring-Word separator (- / _ / ., default -)
max_lengthinteger-Maximum slug length (1–200)
lowercaseboolean-Lowercase the slug (default true)

text.convert_string_case (GET /v1/string/case) converts existing ASCII identifiers between camel, snake, kebab, and similar cases; Japanese only supports lower/upper. This API targets URL paths, document IDs, and navigation keys from human-readable titles, romanizing Japanese when locale is ja via kuromoji + kuroshiro before normalization.

MCP tool: text.generate_slug

Example 1: Japanese title (locale: ja)

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/slugify" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Thousand API — 祝日カレンダー機能",
    "locale": "ja"
  }'

Response example:

{
  "input": "Thousand API — 祝日カレンダー機能",
  "slug": "thousand-api-shukujitsu-karendaa-kinou",
  "truncated": false,
  "char_replaced": ["—"]
}

Example 2: English text (locale: en)

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/slugify" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Hello World! This is a Test.",
    "locale": "en"
  }'

Response example:

{
  "input": "Hello World! This is a Test.",
  "slug": "hello-world-this-is-a-test",
  "truncated": false,
  "char_replaced": ["!", "."]
}

Example 3: separator and max_length

Request example:

curl -X POST "https://api.thousand-api.com/v1/text/slugify" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "My Long Document Title Here And More",
    "locale": "en",
    "separator": "_",
    "max_length": 30
  }'

Response example:

{
  "input": "My Long Document Title Here And More",
  "slug": "my_long_document_title_here",
  "truncated": true,
  "char_replaced": []
}

Response fields:

ParameterDescription
inputThe request text echoed back
slugGenerated URL-safe slug
truncatedTrue when max_length truncated the slug
char_replacedCharacters removed or replaced (unique, order of first appearance)

Response:

Japanese processing uses the same Lambda as /v1/ja/convert (kuromoji dictionary). The first request after a cold start may take several seconds.

Japanese Text Conversion

Convert Japanese text to hiragana, katakana, or romaji. Uses kuromoji morphological analysis for accurate conversion of proper nouns.

MCP tool: text.convert_japanese

GET /v1/ja/convert

Parameters:

ParameterTypeRequiredDescription
textstringJapanese text to convert (max 1000 characters)
tostringhiragana / katakana / romaji

Request example:

curl "https://api.thousand-api.com/v1/ja/convert?text=%E6%9D%B1%E4%BA%AC%E9%83%BD%E6%B8%8B%E8%B0%B7%E5%8C%BA&to=hiragana" \
  -H "x-api-key: YOUR_API_KEY"

Response example:

{
  "text": "東京都渋谷区",
  "to": "hiragana",
  "result": "とうきょうとしぶやく"
}