Subscript generator
Type H2O and copy H₂O: digits, plus and minus signs and the letters Unicode lowers, such as a, n and x, become real subscript characters that stay lowered wherever you paste them. Capitals pass through unchanged. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Text
- H2O
- Result
- H₂O
- Length
- 3
- Original length
- 3
- Mapped
- 1
Unicode subscript characters sit below the baseline inside the string itself, so chemical formulas, sequence indices, and footnote-style labels survive in places that strip HTML, markdown, fonts, and rich-text controls. A subscript generator maps ordinary digits and the Latin letters that Unicode actually defines as subscript forms onto those lowered code points, then leaves everything else in place so a formula such as H2O becomes H₂O and a label such as an becomes ₐₙ. Writers paste those glyphs into captions, product titles, academic notes, chat messages, and worksheets because the style travels with the characters rather than with a stylesheet. This capability walks each Unicode scalar value of your input, replaces digits zero through nine, supported letters including a, e, h, i, j, k, l, m, n, o, p, r, s, t, u, v, and x, and the operators plus, minus, equals, and parentheses, then reports unique characters that did not convert.
How Unicode subscript maps digits, letters, and operators
Unicode subscript is a fixed set of code-point assignments, mostly in the Superscripts and Subscripts block, not a font baseline offset that a word processor applies and later discards. Digits map to U+2080 through U+2089, so zero becomes ₀, one becomes ₁, two becomes ₂, and nine becomes ₉.
A documented subset of Latin lowercase letters has official subscript forms: a, e, h, i, j, k, l, m, n, o, p, r, s, t, u, v, and x map to ₐ ₑ ₕ ᵢ ⱼ ₖ ₗ ₘ ₙ ₒ ₚ ᵣ ₛ ₜ ᵤ ᵥ ₓ. Operators plus, minus, equals, and parentheses become ₊ ₋ ₌ ₍ ₎ so a fragment such as n+1 can become ₙ₊₁ without leaving the lowered alphabet.
The converter walks each Unicode scalar value in your string, replaces every plain character that has a table entry with the matching subscript code point, and leaves everything else in place. Letters without a standard subscript form — including b, c, d, f, g, q, w, y, z and essentially all uppercase Latin — are not invented, approximated, or dropped; they pass through and appear once each in the unmapped list so callers can audit coverage.
Because a few of these glyphs sit outside the most common ASCII range, the implementation iterates by code point rather than by UTF-16 unit, so a single emoji is never split in half.
Where Unicode subscript shows up in real work
Mathematicians and programmers label sequences, tensor indices, and loop counters with lowered letters and digits, writing aₙ or xᵢ without HTML so the label survives in a ticket, a chat, or a CSV cell. Product and e-commerce teams generate title variants for marketplaces that accept plain text only but still render subscript digits in customer feeds, for example area units, model generations, or ingredient lists.
Support desks receive subscript paste from customers and want a documented alphabet so they can see which glyphs are real Unicode subscripts and which characters never converted. If you need HTML sub tags, CSS vertical-align, Unicode superscript, mathematical bold or fraktur styling, Braille translation, or small capitals, treat those as separate search intents and landings rather than overloading this Unicode subscript page, which exists specifically for digits and the letters Unicode actually defines as subscript forms.
What you can do with it
Chemical formulas in plain text
Turn H2O, CO2, and C6H12O6 into H₂O, CO₂, and C₆H₁₂O₆ so element symbols stay large while counts drop below the baseline.
Math indices and sequence labels
Encode aₙ, xᵢ, and n+1 as ₐₙ, ₓᵢ, and ₙ₊₁ for captions, tickets, and notes that strip HTML sub tags.
FAQ
Which characters become Unicode subscript?
Digits 0–9, Latin letters that Unicode defines as subscript forms (a, e, h, i, j, k, l, m, n, o, p, r, s, t, u, v, x), and the operators + - = ( ). Other characters pass through and are listed in unmapped.
Why do H and O stay large in H2O?
Unicode does not define uppercase Latin subscript letters. Uppercase element symbols pass through; only the digits (and any supported lowercase letters) convert, which is the usual chemical-formula look.
Is this the same as HTML <sub> or CSS vertical-align?
No. This emits Unicode subscript code points that travel inside the text itself. HTML tags and CSS baseline shifts are separate mechanisms that platforms often strip.
What happens to letters such as b, q, or w?
They stay in the result in their original form. Unicode has no standard subscript for those letters, so they are listed in unmapped rather than faked.
What does it cost?
The browser tool is free and runs locally.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/str/subscript-generator \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"H2O"}'const res = await fetch("https://api.kit.forhosting.com/str/subscript-generator", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "H2O"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/str/subscript-generator",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "H2O"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/str/subscript-generator", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"H2O"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"H2O"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/str/subscript-generator", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"text": "H2O"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "str.subscript_generator",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_chars | 65536 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
What you send and what you get back
Send a required string field named text containing the formula fragment, chemical formula, index label, or caption you want lowered. Classic checks include converting H2O into H₂O while listing uppercase H and O as unmapped, converting supported letters such as a, n, and x into ₐₙₓ, converting n+1 into ₙ₊₁, converting C6H12O6 into C₆H₁₂O₆, and confirming that a numeric or empty text field is rejected rather than silently coerced. Aliases such as input, string, value, content, message, data, and s are accepted for the same field so scripts and spreadsheets can reuse existing payload shapes without renaming columns. On success the response echoes the original text, returns result as the converted string, length as the Unicode scalar length of that result, original_length as the scalar length of the input, mapped as the count of characters that hit the table, unmapped_count and unmapped as the unique characters that passed through, and method as the fixed tag to_subscript for logs. Missing text, null, empty strings, numbers, objects, arrays, booleans, and strings longer than the documented maximum fail with invalid_input and a clear English message that names the problem. Validation failures do not consume prepaid balance.
Where Unicode subscript shows up in real work
Chemistry teachers and lab notebooks still need copy-pasteable subscripts when a platform will not keep rich text: carbon dioxide becomes CO₂, water becomes H₂O, and glucose becomes C₆H₁₂O₆ because only the digits map while uppercase element symbols stay full size, which is exactly the typesetting convention those formulas expect. Because this capability is a pure parse engine, API pricing is the published base of $0.002 per successful item and failed validation does not consume balance.
Integration use cases
Deterministic fixtures for content pipelines
Generate golden subscript strings so scheduled-post tools and CI checks always apply the same Unicode alphabet.