Skip to content
ZeroServer.tools
All guides

JavaScript Regex Flags Explained: g, i, m, s, u, y, d

June 9, 2026 · 4 min read

JavaScript has seven regex flags. Most developers know g and i, but the newer flags (s, u, y, d) are less understood — and they solve real problems. This guide explains all seven with clear examples.

How flags work

Flags are added after the closing slash of a regex literal, or as the second argument to new RegExp():

const re1 = /pattern/gi;            // literal — g + i flags
const re2 = new RegExp("pattern", "gi"); // constructor form

You can check which flags are active via re.flags (returns a sorted string like "gi").


g — global

The g flag makes the regex find all matches instead of stopping at the first.

"aaa".match(/a/)   // → ["a"]         — one match
"aaa".match(/a/g)  // → ["a","a","a"] — all matches

Without g, match() returns the first match plus capture groups. With g, it returns a flat array of all matched substrings (no capture group info). Use matchAll() with g to get an iterator of full match objects:

const re = /(\w+)@(\w+)/g;
for (const m of "a@b c@d".matchAll(re)) {
  console.log(m[1], m[2]); // "a" "b", then "c" "d"
}

Gotcha: Stateful regexes. A regex object with g tracks lastIndex. Calling exec() repeatedly advances through the string. Reset lastIndex to 0 if you reuse the same regex object on different strings.


i — case-insensitive

Makes character matching ignore case differences:

/hello/i.test("HELLO")  // true
/[a-z]/i.test("Z")      // true — range expanded to both cases

Affects character classes and literals, but not backreferences:

/(a)\1/i.test("Aa")  // false — backreference must match the actual captured text

m — multiline

Changes ^ and $ anchors to match at the start/end of each line rather than the entire string:

const text = "line1\nline2\nline3";

text.match(/^\w+/gm)  // → ["line1", "line2", "line3"]
text.match(/^\w+/g)   // → ["line1"]  — without m, ^ only matches start-of-string

The m flag does not make . match newlines — that's what s does.


s — dotAll (ES2018)

By default, . matches any character except \n, \r, , and . The s flag removes that exception:

/foo.bar/.test("foo\nbar")   // false
/foo.bar/s.test("foo\nbar")  // true

This is especially useful when matching multi-line blocks like HTML tags or JSON fragments:

const html = "<div>\n  content\n</div>";
html.match(/<div>(.*?)<\/div>/s)?.[1].trim()  // "content"

u — unicode (ES2015)

Enables full Unicode mode. Affects:

  1. Surrogate pairs — without u, a regex operates on 16-bit code units; \u{1F600} (emoji) is treated as two separate characters. With u, it's treated as one:
/^.$/u.test("😀")   // true  — one emoji = one character
/^.$/.test("😀")    // false — two UTF-16 code units
  1. \p{...} Unicode property escapes — only work with u:
/\p{Emoji}/u.test("😀")    // true
/\p{Script=Arabic}/u.test("مرحبا")  // true
  1. Strict mode — invalid escape sequences throw instead of being silently ignored.

Use u any time you're working with multilingual text, emoji, or Unicode ranges.


y — sticky (ES2015)

The y flag works like g but requires the match to start exactly at lastIndex — it doesn't scan forward:

const re = /\d+/y;
re.lastIndex = 4;

re.exec("abc 123")   // → ["123"]  — match starts at index 4
re.exec("abc 123")   // → null     — lastIndex is now 7, no match there

Sticky is useful for building hand-written tokenizers and parsers where you advance through a string position by position and want guaranteed sequential matching.


d — indices (ES2022)

Adds a indices property to match results, giving you the start and end positions of each capture group:

const m = "2026-06-09".match(/(\d{4})-(\d{2})-(\d{2})/d);
m.indices[0]  // [0, 10]  — full match
m.indices[1]  // [0, 4]   — year
m.indices[2]  // [5, 7]   — month
m.indices[3]  // [8, 10]  — day

Before d, you had to compute positions manually. It's now available in Chrome 90+, Safari 16+, Firefox 131+, and Node 16+.


Combining flags

Flags can be combined freely:

/pattern/gim   // global, case-insensitive, multiline
/pattern/gsu   // global, dotAll, unicode

The only incompatible pair is u and v (the newer verbose Unicode flag) — they can't be used together.


Quick reference

Flag Name What it does
g global Find all matches, not just the first
i case-insensitive Ignore case when matching
m multiline ^/$ match start/end of each line
s dotAll . matches newlines
u unicode Full Unicode mode + \p{}
y sticky Match only at lastIndex, no scanning
d indices Add indices array to match results

Test flags interactively

The Regex Tester lets you toggle any combination of flags and see all matches highlighted in real-time — including the substitution and unit-test tabs for verifying your patterns against expected inputs.