1001Ferramentas
🚩Validators

Flag Emoji Validator

Check if an emoji is a valid country flag (Regional Indicator Symbols). Shows ISO 3166-1 alpha-2.

Flag emoji validation: how Unicode encodes a country in two characters

A flag emoji like 🇧🇷 is not a single character in Unicode — it is a pair of Regional Indicator Symbol Letters (RIS) that together form the ISO 3166-1 alpha-2 country code. The flag of Brazil is the letters B + R rendered as a sequence: 🇧 (U+1F1E7) followed by 🇷 (U+1F1F7). The flag of the United States is 🇺 + 🇸 (U+1F1FA + U+1F1F8). The font and operating system are the only thing that turns the pair into an actual flag glyph — at the byte level it is just two indicator letters.

This means flag validation has two layers: (1) is the input syntactically two Regional Indicator codepoints, and (2) does the resulting alpha-2 pair correspond to a recognised ISO 3166-1 country? A string can pass the first check and still fail the second — combinations like 🇽🇽 (XX) are well-formed sequences but render as the two raw letters because no country has that code.

The Regional Indicator block: U+1F1E6 to U+1F1FF

Unicode reserves 26 codepoints in the Supplementary Multilingual Plane for the Regional Indicators:

  • U+1F1E6 = 🇦, U+1F1E7 = 🇧, U+1F1E8 = 🇨, ... U+1F1FF = 🇿
  • Each indicator is 4 bytes in UTF-8 — a flag emoji is therefore 8 bytes, twice the length of a basic emoji.
  • String.length in JavaScript returns 4 for a single flag (two surrogate pairs), not 1.
  • To count flags correctly use the iterator protocol: [...'🇧🇷'].length === 2, then group pairs.

The validation regex with the Unicode flag is direct:

const flagRegex = /^[\u{1F1E6}-\u{1F1FF}]{2}$/u

function isFlagEmoji(str) {
  if (!flagRegex.test(str)) return false
  const chars = [...str]
  const a = chars[0].codePointAt(0) - 0x1F1E6
  const b = chars[1].codePointAt(0) - 0x1F1E6
  const code = String.fromCharCode(65 + a, 65 + b)  // alpha-2
  return ISO_3166_1.has(code)
}

Subdivisions, special flags and Tag Sequences

A handful of flags fall outside the Regional Indicator pattern:

  • England 🏴󠁧󠁢󠁥󠁮󠁧󠁿, Scotland 🏴󠁧󠁢󠁳󠁣󠁴󠁿, Wales 🏴󠁧󠁢󠁷󠁬󠁳󠁿 — use a Tag Sequence: a black flag base (U+1F3F4) plus invisible Tag characters spelling out the ISO 3166-2 subdivision code (gb-eng, gb-sct, gb-wls), terminated by U+E007F.
  • Pirate flag 🏴‍☠️ — black flag + ZWJ (Zero-Width Joiner) + skull and crossbones.
  • Rainbow flag 🏳️‍🌈 — white flag + variation selector + ZWJ + rainbow.
  • Transgender flag 🏳️‍⚧️ — same ZWJ pattern with the gender symbol.

The total of country/territory flags is roughly 250, matching the active ISO 3166-1 list. The Unicode CLDR (Common Locale Data Repository) provides localised country names for each — useful when you want to show "Brasil" next to 🇧🇷 in a Portuguese UI and "Brazil" in an English UI.

Platform inconsistencies and political sensitivities

Rendering is platform-dependent and politically loaded. Apple's emoji font ships real flag glyphs for every country; Google's Noto Color Emoji does the same. Microsoft Windows historically rendered the bare Regional Indicator letters instead of a glyph — that finally changed with Windows 11. The Taiwan flag 🇹🇼 is the canonical example: on iOS the device hides it when the system region is set to mainland China; some Chinese-market Android builds skip it entirely. 🇽🇰 Kosovo was added late and is still inconsistent. 🇪🇺 European Union uses the special code EU that is technically reserved, not assigned.

For applications, this means: never assume the same flag emoji will render identically on every device. Show the country name as a fallback, especially in accessibility contexts where screen readers may announce only the alpha-2 code.

Use cases in Brazilian apps

Flag emojis appear in language switchers (🇧🇷 / 🇺🇸 / 🇪🇸), country pickers in e-commerce checkout, WhatsApp Status, Instagram bios, push-notification badges and CDN region indicators. The biggest pitfall is using a flag to indicate a language instead of a country — Spanish is spoken in 21 countries, and choosing 🇪🇸 over 🇲🇽 is a political signal users notice. The safe pattern is to label the option by language code (pt-BR, en-US) and put the flag next to it as decoration, never as the sole identifier.

FAQ

How many country flags exist? About 250, matching ISO 3166-1. Subdivisions add a few more via Tag Sequences (England, Scotland, Wales, Texas in some fonts), and special flags (pirate, rainbow, transgender) use ZWJ sequences.

Why does my code see length 4 for 🇧🇷? JavaScript strings are UTF-16. Each Regional Indicator is in the supplementary plane and occupies two surrogate code units, so a flag is 4 UTF-16 code units. Use [...str] or str.codePointAt to count actual characters.

Why does the Taiwan flag disappear on some devices? Apple and some Chinese-market Android builds hide 🇹🇼 when the device region is set to mainland China, for regulatory reasons. The underlying codepoint sequence is still there in the data — only the rendered glyph changes.

Are subdivision flags Tag Sequences? Yes. England, Scotland and Wales use the black-flag base plus ISO 3166-2 codes in Tag characters. Most fonts render them as the regional flag; older fonts fall back to the bare black flag.

Can I validate without an ISO 3166 table? Only structurally — you can confirm the input is two Regional Indicators, but you cannot tell whether the pair encodes a real country without the lookup list. Combinations like 🇽🇽 pass the regex but are not flags.

Related Tools