RegexLab

Regex Flags Explained: g, i, m, s, u and y

6 min readUpdated September 2026
A code editor window

Flags are the letters after the closing slash of a regex, as in /pattern/gi. They change how the whole pattern behaves without altering a single character of it, and the same expression can match once or many times, care about case or not, depending on which flags are set. Knowing the six JavaScript flags turns a lot of confusing regex behaviour into something predictable.

g and i: the everyday pair

The global flag g tells the engine to find every match, not just the first. Without it, methods like replace change only the first occurrence and a match loop returns a single result. Most of the time you want g when you are searching or replacing across a whole string. The tester keeps highlighting all matches regardless, but the g flag is what you would set in real code.

The ignore-case flag i makes letter matching case-insensitive, so /error/i matches Error, ERROR and error alike. It is the simplest flag and the one you reach for constantly when scanning human-written text or log levels where capitalisation is inconsistent.

m and s: lines and dots

The multiline flag m changes what the anchors ^ and $ mean. Normally they match the start and end of the entire string; with m they match the start and end of every line, so ^\d+ finds a number at the beginning of any line in a multiline block. This is essential when a text area holds many records, one per line.

The dotAll flag s lets the dot . match newline characters too. By default . matches any character except a line break, which is usually what you want; but when you need a pattern to span lines — say, to capture everything between two markers across a paragraph — the s flag makes .*? reach across newlines. Combine m and s deliberately, because they solve different problems.

u and y: unicode and sticky

The unicode flag u makes the engine treat the pattern as a sequence of Unicode code points rather than UTF-16 units. It is what lets \u{1F600} and Unicode property escapes like \p{L} work correctly, and it tightens error checking on the pattern. Set u whenever you deal with emoji, non-Latin scripts or astral characters, so a single symbol is not accidentally split in two.

The sticky flag y anchors each match attempt to the current lastIndex position instead of searching forward. It is a specialised tool for tokenizers and parsers that walk a string piece by piece, where each token must begin exactly where the previous one ended. You will rarely need y for ad-hoc searching, but it is invaluable when building a scanner. Toggle any flag in the tester to watch the match set change instantly.

lastIndex: the state everyone forgets

A regex with `g` or `y` is not a pure value — it carries a mutable `lastIndex` that records where the next search should begin. Call `re.test(s)` twice in a row on the same `/\d+/g` object and you get `true` then `false`, because the first call moved the cursor past the match and the second started from there. Declaring such a regex at module scope and reusing it across calls is one of the most common bugs in JavaScript text handling.

Either create the regex inside the function, reset `re.lastIndex = 0` before each use, or drop `g` when you only need a yes-or-no answer. `String.prototype.matchAll` avoids the trap by cloning the regex internally, which is one more reason to prefer it to a hand-rolled `exec` loop. The sticky flag `y` behaves the same way but is stricter still: it anchors each attempt exactly at `lastIndex` instead of searching forward, which is what makes it the right tool for a tokeniser.

The newer flags: d and v

`d`, standardised in ES2022 under the name `hasIndices`, adds an `indices` array to every match: `m.indices[1]` gives the start and end offsets of the first capture group, and `m.indices.groups` does the same for named ones. Before it existed, locating a group inside the original string meant re-searching or adding throwaway capture groups to count characters — a fiddly step that editors, linters and syntax highlighters all needed.

`v`, added in ES2024, is a stricter superset of `u` called `unicodeSets`. It turns character classes into real sets: `[\p{L}--\p{ASCII}]` subtracts one set from another, `[\p{Script=Greek}&&\p{Letter}]` intersects them, and `\q{...}` lets a class contain multi-character strings, which finally makes emoji sequences expressible. You cannot combine `u` and `v` on the same pattern — pick `v` for new code that cares about Unicode, and `u` where you need the wider engine support.

The takeaway

Flags reshape a pattern without changing it: g finds all, i ignores case, m makes ^ and $ per-line, s lets the dot cross newlines, u enables Unicode, and y anchors to lastIndex. Toggle them in the tester and watch the matches respond.

Try it live
Open the regex tester

Try this pattern live with match highlighting.