Specification

This document defines how the Python wcwidth and C11 libwcwidth libraries measure the printable width of characters of a string. This is not meant to be an official standard, but as a terse description of the lowest level API functions wcwidth.wcwidth() and wcwidth.wcswidth() and their relation to higher level functions wcwidth.width(), wcwidth.wcstwidth() and wcwidth.iter_graphemes().

Scope

The lowest level functions wcwidth.wcwidth() and wcwidth.wcswidth() return -1 when any control codes are present. The higher level function wcwidth.width() never returns -1, accepting default arguments, control_codes='parse' and its behavior and options are described by its docstring and specifications of related control codes, XTerm Control Sequences and Kitty Text Sizing Protocol.

Each string yielded by wcwidth.iter_graphemes() may be mapped to wcwidth.wcswidth() to accurately measure the width of a grapheme. wcwidth.iter_graphemes() implements the Unicode Standard Annex #29 rules of Unicode 18.0, the version of this library’s tables, while unicodedata.iter_graphemes(), new in Python 3.15, implements Unicode 17.0. They also differ in return value: wcwidth.iter_graphemes() yields only strings, while unicodedata.iter_graphemes() yields unicodedata.Segment class objects.

Tamil, Kannada and Sinhala text is measured differently than it is segmented, so wcwidth.clip() and wcwidth.wrap() do not measure these scripts correctly. See Virama Conjunct Formation.

The C11 library libwcwidth implements this specification through parallel entry points: wcswidth_u32() and wcswidth_u8() for wcwidth.wcswidth(), wcstwidth_u8() for wcwidth.wcstwidth(), and wcwidth_width_u8() for wcwidth.width(); see the C11 API.

Width of -1

The following have a column width of -1 for function wcwidth.wcwidth()

If any character in sequence contains C0 or C1 control characters, the final return value of wcwidth.wcswidth() is -1, except a control character immediately following ZWJ (U+200D), which Width of 0 consumes.

Width of 0

Any characters with the Default_Ignorable_Code_Point property in DerivedCoreProperties.txt, excluding U+00AD SOFT HYPHEN (width 1) and U+115F HANGUL CHOSEONG FILLER (width 2).

Any characters defined by General Category codes in DerivedGeneralCategory.txt:

Emoji Modifier Fitzpatrick symbols (U+1F3FB through U+1F3FF) are zero-width only when following an emoji base character in sequence; see Width of 2 for standalone.

The NULL character (U+0000).

ZWJ (U+200D) is zero-width, and in sequence by wcwidth.wcswidth() or wcwidth.width() the codepoint immediately following it is consumed as zero-width. For emoji (Extended_Pictographic property) and Regional Indicator sequences this follows the grapheme cluster boundary rules of Unicode Standard Annex #29. After a virama, the following consonant continues the conjunct, see Virama Conjunct Formation.

The second Regional Indicator symbol (U+1F1E6 through U+1F1FF) in a consecutive pair, when measured in sequence by wcwidth.wcswidth() or wcwidth.width(). The first indicator of the pair is Width of 2.

Hangul Jamo Jungseong and “Extended-B” code blocks, U+1160 through U+11FF and U+D7B0 through U+D7FF.

Any characters of category Mc (Spacing Combining Mark), for the single-character function wcwidth.wcwidth(). When measured in sequence by wcwidth.wcswidth(), see Width of 2.

Width of 1

String characters are measured width of 1 when they are not measured as Width of 0 or Width of 2.

Any character with U+FE0E (Variation Selector 15) defined as text style in emoji-variation-sequences.txt, per UTS #51 and Unicode Standard Section 23.4: VS15 subtracts 1 cell from the wide character it directly follows, making the pair width 1. Narrow characters are unchanged.

Note

Variation Selector 15 width specification is contested, see https://github.com/jquast/wcwidth/issues/211

Width of 2

Any character defined by East Asian (Unicode Standard Annex #11) Fullwidth (F) or Wide (W) properties in EastAsianWidth.txt, except those that are defined by the Category codes of Nonspacing Mark (Mn) or Spacing Combining Mark (Mc).

Regional Indicator symbols (U+1F1E6 through U+1F1FF). Though classified as Neutral in EastAsianWidth.txt, terminals universally render these as double-width. A consecutive pair of Regional Indicators forms a flag emoji and is measured as width 2 total (first indicator is 2, second is 0).

Emoji Modifier Fitzpatrick symbols (U+1F3FB through U+1F3FF) when measured standalone (not following an emoji base character). When following an emoji base, they combine with the base and add 0 to total width.

Any characters of Modifier Symbol category, 'Sk' where 'FULLWIDTH' is present in comment of UnicodeData.txt.

Any character with U+FE0F (Variation Selector 16) defined as emoji style in emoji-variation-sequences.txt, per UTS #51 and Unicode Standard Section 23.4: VS16 adds 1 cell to the narrow character it directly follows, making the pair width 2. Wide characters are unchanged.

Any character of non-zero width followed by an Mc (Spacing Combining Mark) character when measured in sequence by wcwidth.wcswidth() or wcwidth.width(). The Mc character caps the cluster width at 2, reflecting its positive advance width as defined in the General Category Values table. Zero-width combining marks (Mn) between the base character and the Mc do not break the association. For example, a consonant followed by a Nukta (Mn) and then a vowel sign (Mc) is measured as a cluster of width 2.

Any grapheme cluster width is limited to 2 cells since 0.8.0, PR #224, which prevents the Mc rule and the virama conjunct sum from exceeding 2 cells.

Virama Conjunct Formation

In Brahmic scripts, IndicSyllabicCategory.txt defines two categories that trigger conjunct formation between consonants: Virama (“may act as a Pure_Killer or Invisible_Stacker depending on context”) and Invisible_Stacker (“not visible by itself; causes conjunct formation or consonant stacking”, the “only as consonant stackers” category described in the Virama section header).

  • A Virama contributes 0 width.

  • Most viramas have category Mn, but six have category Mc (Spacing Combining Mark): these are recognised as viramas, so they begin a conjunct.

  • A Consonant immediately following a Virama adds its width to the current grapheme cluster.

  • The cluster total is capped at 2 cells since 0.8.0, PR #224.

  • Mn marks do not break conjunct context within the same aksara.

  • ZWJ (U+200D) after a virama is consumed without breaking conjunct state, supporting explicit half-form requests (virama + ZWJ + consonant).

See also: L2/23-107 “Proper Complex Script Support in Text Terminals”, the 2023 project proposal that records the missing terminal-width standard, and L2/25-263 for the Text Terminal Working Group’s latest report.