Un carácter invisible es un carácter real que se dibuja como un blanco, o directamente como nada. Los sospechosos habituales son U+00A0, el espacio no separable; U+200B, el espacio de ancho cero; U+FEFF, la marca de orden de bytes; y los once espacios tipográficos que hay entre U+2000 y U+200A. Tus ojos se los saltan. Toda comparación de strings que haga una computadora los cuenta. Por eso una búsqueda en una hoja de cálculo falla con un nombre que se lee perfectamente, por eso se rechaza una contraseña pegada, y por eso dos líneas que parecen idénticas se niegan a fundirse en una.
El síntoma siempre tiene la misma forma: dos cosas que se ven iguales no son iguales. No le pasa nada al software, ni a tus ojos. Hay un carácter de más ahí dentro y no tiene dibujo.
¿Qué caracteres son invisibles?
Dos grupos, con causas distintas.
Espacios que no son la barra espaciadora
La categoría de separadores de espacio de Unicode tiene 17 caracteres. Exactamente uno de ellos es la tecla de tu teclado. Los otros 16 parecen un espacio, miden como un espacio y no coinciden con un espacio.
- U+00A0, el espacio no separable. El más común por mucha diferencia. Llega desde
en HTML, desde el autoformato de Word y, en una Mac, desde Opción más la barra espaciadora. En UTF-8 ocupa 2 bytes, C2 A0, donde un espacio normal ocupa uno. - U+202F, el espacio estrecho no separable. La tipografía francesa pone uno antes de los dos puntos, el punto y coma, el signo de interrogación y el de exclamación, así que un texto en francés copiado de casi cualquier parte viene lleno de ellos.
- De U+2000 a U+200A. Once anchos fijos de composición tipográfica — espacio en, espacio em, tercio de em, espacio fino, espacio capilar, espacio de cifra — que salen de los programas de layout y de los PDF.
- U+3000, el espacio ideográfico. Lo que produce la barra espaciadora en un método de entrada japonés o chino. Es de ancho completo, así que parece dos espacios en lugar de uno sospechoso.
Caracteres sin ancho alguno
Estos ni siquiera parecen un espacio. Ocupan cero píxeles, así que un texto que contiene uno es visualmente idéntico a un texto sin él.
- U+200B, el espacio de ancho cero. Una pista que dice “aquí puedes cortar la línea”. Los gestores de contenido los insertan dentro de palabras largas y de las URL para que el texto pueda cortar ahí.
- U+200C y U+200D, el no unificador y el unificador de ancho cero. Controlan si los caracteres vecinos se fusionan. A diferencia del resto de esta lista, hacen un trabajo real, y eso importa más adelante.
- U+2060, el unificador de palabras. Lo contrario de un espacio de ancho cero: prohíbe el corte.
- U+FEFF, la marca de orden de bytes. Tres bytes, EF BB BF, que van al inicio de un archivo para anunciar su codificación. Los editores agregan una la hayas pedido o no, y termina en medio de un string cada vez que se concatenan dos archivos.
¿Cómo veo los caracteres invisibles?
No puedes, no directamente. Los detectas de tres maneras.
Cuéntalos. Pega el texto en el limpiador de espacios de aquí y te informa lo que encontró antes de cambiar nada: cuántos espacios no separables, cuántos otros espacios Unicode, cuántos caracteres de ancho cero, cuántas líneas terminan en espacio. Un informe vacío descarta toda la categoría en diez segundos.
Compara la longitud con la que esperas. Un código de producto que debería tener 8 caracteres y reporta 9 lleva un pasajero.
Activa el resaltado de tu editor. VS Code enmarca los caracteres invisibles y ambiguos por defecto, una función que agregó después de que la divulgación de Trojan Source en 2021 mostrara que el código fuente se puede preparar para que se lea de una forma para un humano y de otra para un compilador. Casi todos los editores tienen su versión de esto, bajo “mostrar espacios en blanco” o “representar caracteres de control”.
¿Por qué buscar y reemplazar no los quita?
Porque los atajos a los que recurrirías no se ponen de acuerdo sobre qué cuenta como espacio en blanco.
En JavaScript, \s y trim() coinciden con U+00A0 y U+FEFF pero no con U+200B, que está clasificado como carácter de formato y no como espacio. Python se comporta igual: '\xa0'.isspace() es verdadero, '\u200b'.isspace() es falso, así que .strip() lo deja ahí. Excel es peor. TRIM quita solo el espacio ASCII, el carácter 32, y CLEAN solo los caracteres del 0 al 31, así que ninguna de las dos toca el espacio no separable, que es el 160. Ahí necesitas SUBSTITUTE(A1,CHAR(160)," ") antes de que TRIM sirva de algo.
Para ir por ellos explícitamente, usa una regex. Marca Expresión regular en la herramienta de buscar y reemplazar y busca [\u00A0\u200B\u200C\u200D\u2060\uFEFF] — el conjunto de ancho cero más el espacio no separable. Lee el número de coincidencias antes de reemplazar nada.
¿De dónde salen?
Casi siempre de un copiar y pegar que cruza una frontera: una página web, donde cada se copia como un U+00A0 real; un documento de Word, donde el autoformato los agrega alrededor de números e iniciales; un PDF, que arrastra el espaciado que haya usado quien lo compuso.
La marca de orden de bytes es la excepción, y rompe parsers en lugar de comparaciones. La exportación a CSV UTF-8 de Excel pone una al frente del archivo. JSON.parse falla con un U+FEFF inicial, ya que JSON solo admite el espacio, el tabulador, el retorno de carro y el salto de línea como espacio en blanco. El módulo csv de Python te entrega un primer campo llamado \ufeffid salvo que abras el archivo con la codificación utf-8-sig, que existe exactamente para esto. Si una conversión de CSV produce una clave a la que no le ves nada raro, revisa eso primero.
¿Cómo los quito?
Para prosa, reemplaza cada espacio exótico por uno normal y borra directamente los caracteres de ancho cero. Eso es lo que hace el limpiador por defecto: “Reemplazar espacios exóticos” cubre los 16 separadores de espacio no estándar, “Eliminar caracteres invisibles” cubre el conjunto de ancho cero y la marca de orden de bytes, y los conteos de antes y después te dicen cuántos se fueron.
Para código, desactiva primero el recorte de líneas y la unificación de espacios. La indentación es sintaxis en Python, YAML y los Makefiles, y dos espacios al final son un salto de línea forzado en Markdown. Quitar los caracteres de ancho cero es seguro en todos esos casos, y es la opción que de verdad necesitas: un espacio de ancho cero pegado en un archivo fuente produce un error que nadie puede ver leyendo.
Para listas, limpia antes de deduplicar y no después: dos entradas que se diferencian por un espacio no separable al final son dos strings distintos para cualquier rutina de deduplicación que se haya escrito. Eliminar líneas duplicadas de una lista cubre la otra mitad de ese problema, que es decidir si las mayúsculas y el orden de las palabras cuentan como diferencia.
¿Cuándo conviene dejarlos en paz?
Borrarlos todos de golpe está mal al menos tan seguido como está bien.
- Emoji. Un solo emoji de programador es una persona, un unificador de ancho cero y una laptop. Quita el unificador y te quedan dos emoji separados. Los emoji de familia se desarman igual.
- Texto en persa, árabe y escrituras índicas. El no unificador de ancho cero no es decoración en persa: separa partes de una palabra que no deben fusionarse, y borrarlo cambia cómo se lee la palabra. El unificador hace el mismo trabajo en devanagari.
- Tipografía deliberada. Un espacio no separable entre un número y su unidad está ahí para impedir que un corte de línea parta “10 km” por la mitad. Un limpiador no puede distinguir ese de uno accidental, y aplasta los dos.
Ese es el límite honesto de toda herramienta de esta categoría: encuentra caracteres, no puede leer intenciones.
Lo que un limpiador de espacios no va a atrapar
Varios problemas de caracteres invisibles se ven idénticos desde afuera y necesitan otra solución:
- Homoglifos. Una а cirílica y una a latina se dibujan igual y son caracteres distintos. Ninguna limpieza de espacios hace que coincidan. Si un string sigue sin comparar igual después de una limpieza, este es el siguiente sospechoso.
- El guion suave, U+00AD. Invisible hasta que la línea se corta ahí, momento en el que aparece un guion. Word y las herramientas de silabeo los producen, y la mayoría de los limpiadores los deja en paz porque no son espacios.
- Los caracteres de control bidireccional, de U+202A a U+202E y de U+2066 a U+2069. Reordenan cómo se muestra el texto sin cambiar lo que contiene. Este es el truco de Trojan Source: un problema de seguridad más que de prolijidad.
- Los finales de línea. Finales CRLF de Windows mezclados con finales LF de Unix hacen que un diff declare que cambiaron todas las líneas, y ninguna página con una caja de texto puede arreglarlo. HTML normaliza el contenido de un textarea a saltos de línea simples, así que los retornos de carro ya no están para cuando un script llega a verlos. Arréglalo en tu editor, con
dos2unix, o en la configuración de conversión de git.
Los cuatro tienen la misma firma que un espacio invisible, y ninguno responde al mismo tratamiento. Averiguar cuál de ellos tienes es la mayor parte del trabajo.
El limpiador de espacios enumera lo que encontró por tipo antes de tocar nada, que es la parte que vale la pena usar: saber que el texto contiene cuatro espacios no separables y una marca de orden de bytes te dice más que una versión limpia sin ninguna explicación. Funciona dentro de la página, así que nada de lo que pegues se envía a ningún lado.
Si llegaste aquí porque una búsqueda no encontraba una palabra que está visiblemente en el documento, el carácter invisible es solo una de las razones por las que eso pasa. Buscar y reemplazar: los errores que te cuestan una hora repasa las demás, incluidas las comillas tipográficas y el intercambio en dos sentidos que se come las dos palabras.
Preguntas frecuentes
¿Qué son los caracteres invisibles en un texto?
Son caracteres Unicode que se dibujan como un blanco o directamente no se dibujan, como el espacio no separable (U+00A0), el espacio de ancho cero (U+200B) y la marca de orden de bytes (U+FEFF). Ocupan una posición en el string y cuentan para su longitud, así que una computadora trata un texto que contiene uno como distinto de un texto sin él, aunque los dos se vean idénticos.
¿Cómo encuentro caracteres invisibles en un string?
Pégalo en una herramienta que los cuente por tipo, o compara el número de caracteres con la longitud que esperas. La mayoría de los editores de código también puede resaltarlos: VS Code enmarca los caracteres invisibles y ambiguos por defecto. Una inspección visual a secas nunca va a funcionar, que es justamente el problema.
¿Por qué mi búsqueda no encuentra una palabra que está claramente ahí?
Normalmente porque uno de los espacios de esa palabra no es un espacio normal. Un espacio no separable es idéntico píxel a píxel a uno común y no coincide con él, así que buscar "New York" falla en un texto que contiene "New" más U+00A0 más "York". Las comillas tipográficas copiadas de Word causan el mismo fallo silencioso.
¿Por qué TRIM no quita los espacios en mi hoja de cálculo?
TRIM de Excel solo quita el carácter 32, el espacio ASCII, y CLEAN solo quita los caracteres del 0 al 31. El espacio no separable es el carácter 160, así que ninguna de las dos funciones lo toca. Envuelve la celda en SUBSTITUTE(A1,CHAR(160)," ") primero y entonces TRIM funcionará como esperas.
¿Es seguro eliminar todos los caracteres de ancho cero?
No siempre. El unificador de ancho cero mantiene unidas las secuencias de emoji, así que quitarlo convierte un emoji de familia en varias personas sueltas. El no unificador de ancho cero tiene valor gramatical en persa y en escritura árabe. En prosa sencilla en inglés, quitarlos es seguro y suele ser lo correcto.
¿Qué es una marca de orden de bytes y por qué me rompe el archivo?
Es U+FEFF, tres bytes al inicio de un archivo UTF-8 que anuncian la codificación. Muchos parsers no la esperan: JSON.parse falla si está al principio, y un lector de CSV va a reportar el encabezado de la primera columna como un nombre desconocido. Python lo resuelve con la codificación utf-8-sig, que quita la marca mientras lee.
Última actualización 19 de septiembre de 2026