Data e Tempo Matemática Conversores Ferramentas de Texto Dia a Dia Geradores Blog Sobre Contato
A palavra ação contada de quatro formas diferentes: 4 unidades UTF-16, 4 pontos de código, 4 grafemas e 6 bytes, e a mesma palavra em forma decomposta contando 6
Texto

Por que o Mesmo Texto Tem Contagens de Caracteres Diferentes

Você escreve uma frase, cola no contador de caracteres, e ele diz 120. Cola no campo do site de destino, e ele acusa 124. Salva no banco de dados, e o sistema reclama que passou do limite. Os três números são diferentes e nenhum deles está errado: eles contam coisas diferentes.

Quatro unidades, um texto só

Um texto pode ser medido de pelo menos quatro maneiras, e cada uma serve a um propósito.

  • Unidades UTF-16 são o que a maioria dos contadores em navegador entrega, porque é o que a linguagem devolve nativamente. Caracteres fora do plano básico ocupam duas unidades.
  • Pontos de código são os números que o Unicode atribui a cada caractere codificado.
  • Grafemas são o que uma pessoa aponta na tela e chama de caractere.
  • Bytes são o espaço ocupado no armazenamento, e dependem da codificação usada.

A tabela abaixo mostra as quatro medidas para alguns textos. Todos os valores foram medidos, não estimados.

Texto Unidades UTF-16 Pontos de código Grafemas Bytes UTF-8
não 3 3 3 4
café (composto) 4 4 4 5
café (decomposto) 5 5 4 6
ação (composto) 4 4 4 6
ação (decomposto) 6 6 4 8
🇧🇷 4 2 1 8
família 👨‍👩‍👧 16 13 9 27

Repare na coluna de grafemas: ela é a única que concorda com o que os olhos veem em todas as linhas. As outras três discordam por motivos diferentes.

O caso que mais engana em português

A palavra ação escrita de duas formas idênticas na tela: em NFC com quatro pontos de código e em NFD com seis, porque o cê-cedilha e o a-til se separam em letra e acento
As duas linhas são a mesma palavra e têm a mesma aparência. A de baixo guarda o acento como um caractere próprio, colado na letra anterior.

O Unicode permite escrever uma letra acentuada de duas formas. O ç pode ser um único ponto de código, ou pode ser a letra c seguida de uma cedilha combinante, que se desenha por cima da anterior. O ã pode ser um ponto de código, ou um a seguido de um til combinante.

O UAX #15 chama isso de equivalência canônica e define as duas formas:

Normalization Form D (NFD): Canonical Decomposition

Normalization Form C (NFC): Canonical Decomposition, followed by Canonical Composition

O mesmo anexo é claro sobre o que as duas têm em comum: sequências canonicamente equivalentes “representam o mesmo caractere abstrato” e, quando exibidas corretamente, “devem sempre ter a mesma aparência visual e comportamento”.

Aí está o problema prático. A palavra ação em forma composta tem 4 pontos de código. Em forma decomposta tem 6, porque ganha dois acentos que passaram a contar separado. Nada muda na tela. Tudo muda no contador, na comparação entre duas strings que deveriam ser iguais e no campo com limite rígido.

Texto decomposto costuma chegar por cópia entre sistemas, e a diferença é invisível até alguém contar.

Por que grafema não é ponto de código

A quarta coluna da tabela mostra o outro lado do mesmo problema. A bandeira do Brasil ocupa 2 pontos de código e 1 grafema; um emoji de família ocupa vários pontos de código e continua sendo um desenho só.

O UAX #29 explica por que a distinção existe:

A single Unicode code point is often, but not always the same as a basic unit of a writing system for a language, or what a typical user might think of as a “character”.

E define o grafema como a aproximação programática dessa unidade percebida, descrita no anexo como uma aproximação de melhor esforço que pode ser determinada de forma inequívoca por um programa. É a contagem que corresponde ao que o leitor enxerga, e a que faz sentido quando o limite é de leitura, não de armazenamento.

Qual número olhar

Situação Contagem que importa
Limite de campo em banco de dados Bytes, geralmente UTF-8
Limite anunciado por uma interface O que aquele campo contar, conferido nele
Texto que uma pessoa vai ler Grafemas
Comparar dois textos que deveriam ser iguais Qualquer uma, depois de normalizar

A linha do banco de dados é a que mais gera surpresa em português. Em UTF-8, letras sem acento ocupam 1 byte e acentuadas ocupam 2. A palavra ação tem 4 caracteres e 6 bytes. Um campo dimensionado como se caractere e byte fossem a mesma coisa vai estourar antes do esperado, e vai estourar mais cedo em textos com muito acento.

Como conferir o seu texto

O trecho abaixo roda no console de qualquer navegador e mostra as quatro medidas, além de avisar se o texto estava decomposto:

const t = "ação";
const seg = new Intl.Segmenter("pt-BR", { granularity: "grapheme" });

console.log({
  utf16: t.length,
  pontosDeCodigo: [...t].length,
  grafemas: [...seg.segment(t)].length,
  bytes: new TextEncoder().encode(t).length,
  estavaDecomposto: t.normalize("NFC").length !== t.length,
});

Se estavaDecomposto vier true, o texto chegou com acentos separados. Normalizar para NFC resolve a contagem e a comparação, porque o UAX #15 garante que duas strings equivalentes produzem exatamente a mesma forma normalizada. O que a normalização não resolve é a diferença entre contar caracteres e contar bytes, que continua valendo depois dela.

Fontes e metodologia

As definições de normalização e de grafema vêm dos anexos técnicos do Unicode listados abaixo, abertos na data indicada. Todos os números das tabelas foram medidos, não estimados: rodei cada string no Node.js e conferi String.length, o total de pontos de código, o total de grafemas pelo Intl.Segmenter e o tamanho em bytes UTF-8, com o mesmo trecho de código reproduzido no texto para você refazer a medição. Plataformas específicas podem aplicar regras próprias de contagem que não estão documentadas publicamente, e por isso o guia não afirma o limite de nenhuma delas: quando o limite for rígido, a conferência que vale é a do próprio campo de destino.

  1. UAX #15 — Unicode Normalization Forms, revisão 57 (30/07/2025) Unicode Consortium As definições de NFD como decomposição canônica e de NFC como decomposição canônica seguida de composição canônica, e o princípio de equivalência canônica entre sequências que representam o mesmo caractere abstrato e devem ter a mesma aparência visual. Consultado em
  2. UAX #29 — Unicode Text Segmentation, revisão 47 (17/08/2025) Unicode Consortium A definição de grafema como a aproximação programática do que o usuário percebe como um caractere, e a constatação de que um único ponto de código nem sempre corresponde a essa unidade percebida. Consultado em

Perguntas frequentes

Por que o contador mostra um número e o site de destino mostra outro?

Porque os dois podem estar contando unidades diferentes. Contadores em navegador normalmente usam unidades UTF-16, que é o que a linguagem entrega de forma nativa; bancos de dados costumam limitar bytes; e algumas interfaces contam o que o usuário percebe como caractere. Nenhum dos três está errado, e por isso a conferência final deve ser feita no próprio campo de destino.

O que é NFC e NFD?

São formas de normalização definidas pelo Unicode. Pelo UAX #15, NFD é a decomposição canônica, em que a letra e o acento ficam guardados separadamente, e NFC é a decomposição seguida de composição canônica, que junta os dois num único ponto de código. As duas produzem a mesma coisa na tela e tamanhos diferentes na memória.

Por que a palavra "ação" às vezes conta 6 caracteres?

Porque ela chegou em forma decomposta. Em NFC, "ação" tem 4 pontos de código; em NFD, o ç vira c mais uma cedilha combinante e o ã vira a mais um til combinante, somando 6. O texto continua idêntico visualmente, e é por isso que o problema passa despercebido até algum campo com limite rígido recusar o conteúdo.

De onde vem texto em NFD?

Normalmente de cópia entre sistemas. Alguns ambientes armazenam nomes de arquivo e texto em forma decomposta, e o conteúdo mantém essa forma quando é colado adiante. Como a diferença é invisível, ela só aparece quando alguém conta os caracteres ou compara duas strings que deveriam ser iguais.

Como um emoji pode contar mais de um caractere?

Muitos emojis são sequências. A bandeira do Brasil é formada por dois símbolos indicadores regionais, e emojis de família juntam várias figuras com um caractere invisível de junção entre elas. O leitor vê um desenho só; a contagem por pontos de código vê vários.

Qual contagem devo usar para um limite de banco de dados?

Bytes, quase sempre em UTF-8. Nessa codificação, letras sem acento ocupam 1 byte, acentuadas ocupam 2 e emojis costumam ocupar 4. Uma frase curta em português já ocupa mais bytes do que caracteres, e um campo dimensionado como se os dois fossem iguais estoura antes do esperado.

Como sei em que forma o meu texto está?

Compare o texto com a versão normalizada dele. Se o comprimento mudar depois de normalizar para NFC, ele estava decomposto. O trecho de código deste guia faz exatamente essa checagem e roda em qualquer console de navegador.

Normalizar o texto resolve o problema?

Resolve o descompasso de contagem e de comparação, porque o UAX #15 garante que duas strings equivalentes produzem exatamente a mesma forma normalizada. O que ele não resolve é a diferença entre contar caracteres e contar bytes, que continua existindo depois da normalização.