Character Limits Cheatsheet: Every Limit That Matters for Developers
Meta titles, descriptions, Twitter, SMS, Open Graph, HTTP headers, SQL identifiers — every character limit you'll actually hit, with the Unicode caveats that will bite you.
Knowing that Twitter allows 280 characters is one of those facts that sounds simple until you’re building an SMS sender and hitting truncation bugs on emoji, or writing meta descriptions that show up ellipsized in search results. The limits matter, the edge cases matter more, and “character” means something different depending on where you’re counting.
This is the cheatsheet. Use the Word Counter on this site to count characters and words in real time as you write or paste content.
What “character” actually means
Before the limits: a “character” is not a byte, and it’s not always one Unicode code point either.
Bytes vs code points vs grapheme clusters
A byte is 8 bits. ASCII characters are 1 byte each. Beyond ASCII, it depends on the encoding:
- UTF-8 encodes code points above U+007F in 2–4 bytes. The Euro sign
€is U+20AC — 3 bytes in UTF-8. Most emoji are 4 bytes. - UTF-16 uses 2 bytes for most code points, 4 bytes for anything above U+FFFF (surrogate pairs). JavaScript uses UTF-16 internally, so
"😀".lengthreturns2in JavaScript.
A Unicode code point is the abstract number (U+0041 = A, U+1F600 = 😀). Most platforms count by code points when they say “characters.”
A grapheme cluster is what a human calls “one character” — the visible unit. The flag emoji 🇩🇪 is actually two code points (U+1F1E9 U+1F1EA). The letter é can be one code point (U+00E9, precomposed) or two (U+0065 + U+0301, base + combining accent). Both look identical. Counting code points instead of grapheme clusters is the bug that causes string truncation to split combining characters.
The practical rules
| Platform | What they count |
|---|---|
| Twitter/X | Unicode code points (weighted: most are 1, URLs are 23) |
| SMS (GSM-7) | GSM-7 characters (7-bit alphabet, 160 per segment) |
| SMS (Unicode) | UTF-16 code units (70 per segment, 67 with concatenation) |
MySQL VARCHAR(n) | Characters (code points), not bytes |
PostgreSQL VARCHAR(n) | Characters (code points) |
JavaScript string.length | UTF-16 code units (emoji count as 2) |
Python len(string) | Unicode code points |
| HTTP headers | Bytes (RFC 7230 requires US-ASCII in header names) |
SEO and metadata limits
Meta title (page <title>)
Google typically displays 50–60 characters before truncating with an ellipsis. The real limit is pixel-width — approximately 600px on desktop — so a title made of wide characters (W, M) truncates sooner than one made of narrow characters (i, l, t). The 50–60 character rule is a reasonable proxy.
<title>Character Limits Cheatsheet for Developers — Xerobit</title>
<!-- 55 characters — safe zone -->
Google will rewrite your title if it judges it too short, too keyword-stuffed, or not representative of the page. Writing a title that accurately describes the page’s content matters more than hitting exactly 55 characters.
Meta description
Google truncates snippets at roughly 150–160 characters on desktop, 120 characters on mobile. It’s a soft limit — Google sometimes shows more when the query matches text in the description, sometimes shows less.
<meta name="description" content="Every character limit that matters for
developers — meta titles, SMS, HTTP headers, SQL identifiers, and the Unicode
edge cases that cause real bugs." />
<!-- 159 characters — within the safe range -->
Meta descriptions that are too short (under 70 characters) often get replaced by Google with content extracted from the page body. Descriptions that duplicate the title are also commonly replaced.
Open Graph tags
Open Graph controls the preview cards on Facebook, LinkedIn, Slack, iMessage, and most apps that unfurl URLs.
| Tag | Recommended max | Hard limit |
|---|---|---|
og:title | 60 chars | ~100 chars before truncation |
og:description | 200 chars | ~300 chars |
og:image | — | 8MB file size |
LinkedIn and Slack impose their own truncation on top of the Open Graph values. In practice, keep og:title under 60 and og:description under 150 to cover all surfaces.
Social platforms
Twitter / X
| Content | Limit |
|---|---|
| Tweet | 280 characters |
| URL (any length) | Counts as 23 characters |
| Username in @mention | Counts toward 280 |
| Poll option | 25 characters each |
| Alt text | 1,000 characters |
| Bio | 160 characters |
| Display name | 50 characters |
Twitter counts Unicode code points, not bytes. Emoji count as 2 code points (surrogate pair range), then Twitter applies weighting. The URL shortener (t.co) wraps every link regardless of original length, costing you exactly 23 characters.
| Content | Limit |
|---|---|
| Post | 3,000 characters |
| Article title | 150 characters |
| Article body | 125,000 characters |
| Comment | 1,250 characters |
| Company description | 2,000 characters |
| Profile headline | 220 characters |
LinkedIn preview cards (when you share a URL in a post) pull from Open Graph tags. The preview truncates titles at ~70 characters and descriptions at ~200 characters.
YouTube
| Content | Limit |
|---|---|
| Video title | 100 characters (70 before truncation in search) |
| Video description | 5,000 characters |
| Description above fold | ~157 characters before “Show more” |
| Tag | 30 characters per tag |
| Tags total | 500 characters total |
| Channel description | 1,000 characters |
For search click-through, write the first 60–70 characters of the title as a standalone, meaningful description of the video. The description’s first 157 characters are the most valuable — they appear in search snippets and the player before the fold.
SMS and messaging
GSM-7 (standard SMS)
GSM-7 is a 7-bit encoding covering the Latin alphabet plus common symbols. A single SMS segment holds 160 GSM-7 characters. When you concatenate multiple segments (long SMS), each segment’s payload drops to 153 characters because 7 characters are used for the User Data Header that tells the handset how to reassemble segments.
Single SMS: 160 characters maximum
Concatenated: 153 characters per segment (multiple segments)
The GSM-7 alphabet includes A–Z, a–z, digits, common punctuation, and a few special characters (£, €, etc.). Characters outside GSM-7 force the message into Unicode mode.
Unicode SMS
When your message contains any character outside GSM-7 — including emoji, smart quotes " ", and non-Latin scripts — the message switches to UCS-2 encoding (effectively UTF-16):
Single Unicode SMS: 70 characters maximum
Concatenated Unicode: 67 characters per segment
This is the trap that silently doubles your SMS cost. A single emoji in a 160-character message turns it into a 2-segment Unicode message. Monitor this if you’re building notification systems — one curly quote from a CMS field can break your SMS budget assumptions.
iMessage, WhatsApp, Telegram
These use internet protocols and have effectively unlimited message length for practical purposes (WhatsApp caps at 65,536 characters, Telegram at 4,096 per message). The character limit concern for these platforms is in the UI/UX layer, not the transport layer.
HTTP and web protocols
HTTP header fields (RFC 9110)
HTTP header names must be ASCII tokens. Header field values are sequences of visible ASCII and whitespace — no hard length limit in the RFC, but in practice:
| Header | Practical limit |
|---|---|
Cookie header | 4,096 bytes per cookie value; browsers limit total cookie header to ~8,192 bytes |
Authorization header | No RFC limit; proxies often reject headers over 8KB |
URL length | No RFC limit; servers typically enforce 8,192–16,384 bytes; Chrome allows up to ~2MB |
User-Agent | No RFC limit; typically 50–200 bytes |
Nginx’s default large_client_header_buffers is 4 buffers of 8KB each, meaning any single header over 8KB will be rejected with a 400 or 494.
URL length
There is no URL length limit in RFC 3986. The limits come from implementations:
| Context | Limit |
|---|---|
| Chrome | ~2,083,000 characters |
| IE 11 | 2,083 characters (the infamous IE limit) |
| Most web servers | 8,192–16,384 bytes |
| Apache default | 8,190 bytes |
| Nginx default | 8,192 bytes |
For public-facing URLs, stay under 2,048 characters to avoid IE-era proxies and enterprise software with old limits.
Database identifiers
PostgreSQL
| Identifier | Limit |
|---|---|
| Table name | 63 bytes |
| Column name | 63 bytes |
| Index name | 63 bytes |
| Database name | 63 bytes |
PostgreSQL silently truncates identifiers longer than 63 bytes. You can create a table named a_very_long_table_name_that_exceeds_the_limit_somehow_in_some_edge_case_scenario and PostgreSQL will truncate it at 63 bytes without error. The truncated name is what gets stored; using the full name in queries still works because PostgreSQL truncates the query identifier before looking it up.
MySQL / MariaDB
| Identifier | Limit |
|---|---|
| Table name | 64 characters |
| Column name | 64 characters |
| Index name | 64 characters |
| Database name | 64 characters |
| Alias | 256 characters |
MySQL 64 vs PostgreSQL 63 — this difference is irrelevant in practice but worth knowing if you’re writing cross-database migration tooling.
SQLite
SQLite has no documented limit on identifier length and defaults to generous internal limits. In practice: avoid identifiers over 255 characters if you want predictable behavior across SQLite versions.
Ideal content length for SEO
“How long should a blog post be?” is actually two different questions.
For competitive topics
For topics with high search volume and multiple established competitors in the top 10, length correlates with ranking because longer content tends to cover the topic more completely, earn more links, and satisfy more search intents in one document. The practical target for competitive keywords is 1,500–2,500 words.
Beyond 2,500 words, you hit diminishing returns unless the topic genuinely demands more depth (technical references, comprehensive guides). Padding to 3,000 words by repeating yourself doesn’t help — Google’s quality signals reward density, not length.
For informational and long-tail queries
For lower-volume, specific queries (“how to center a div in CSS”), a 500-word post that fully answers the question outperforms a 2,000-word post that buries the answer in filler. 800–1,200 words is typically sufficient for informational queries where the user wants a direct answer.
The actual metric
Word count is a proxy. What matters is whether your post covers the topic better than the current top results. Analyze the top 3–5 results for your target keyword: what questions do they answer, what do they miss, what format do they use? Match depth, exceed quality.
The Word Counter shows your word count and estimated reading time as you write. Aim for a reading time that matches what a reader would actually expect for the topic — 5–8 minutes for a comprehensive technical post, 2–3 minutes for a quick how-to.
The Unicode edge cases you’ll actually hit
Emoji in character-limited fields
A single emoji like 😀 is:
- 1 grapheme cluster (what a human sees as “one character”)
- 1 Unicode code point (U+1F600)
- 4 bytes in UTF-8
- 2 code units in UTF-16 (JavaScript
"😀".length === 2) - 1 character as counted by Twitter, most databases, and most APIs
If you’re validating a VARCHAR(160) in MySQL and a user submits a message with emoji, MySQL counts the emoji as 1 character but stores it as 4 bytes. If your column uses utf8 (MySQL’s broken 3-byte UTF-8), emoji will truncate or error. Use utf8mb4 in MySQL.
Zero-width joiners and flags
The family emoji 👨👩👧👦 is 7 code points joined by zero-width joiners (ZWJ, U+200D). Most platforms count this as 1 “character” visually but may count 7 code points internally. Flag emoji (🇩🇪) are 2 regional indicator code points. These wreak havoc on naive substring() calls — you can split a ZWJ sequence and get a broken, invisible partial emoji.
Use grapheme-aware string libraries when truncating user content:
- Python:
graphemepackage or\Xin regex with theregexmodule - JavaScript:
Intl.Segmenter(modern) or thegraphemernpm package - Ruby:
Unicode::DisplayWidth
Further reading
- Word Counter — live character and word count with reading time estimate
- When to Use 422 vs 400 — error response patterns for APIs that validate content length
- Unicode Standard Annex #29 — Unicode Text Segmentation — the spec for grapheme cluster boundaries
Related posts
- Character Counter — What It Counts and Why It Matters — Character count isn't just about Twitter limits. Email subject lines, SMS, SEO m…
- Letter Counter — Count Letters and Characters in Text — A letter counter tells you how many alphabetic characters are in your text, sepa…
- Paragraph Counter — Count Paragraphs in Text Online — A paragraph counter identifies paragraph boundaries and gives you the exact coun…
- When to Use 422 vs 400 (and Other HTTP Status Code Debates) — 400 means the request is malformed. 422 means it's valid but semantically wrong.…
Related tool
Count words, characters, sentences, paragraphs, and lines. Reading time estimate, char-limit indicators for X, LinkedIn, meta titles, and more.
Written by Mian Ali Khalid. Part of the Dev Productivity pillar.