The d modifier (also called the indices or hasIndices flag) adds an indices property to match results. Each entry tells you exactly where the full match and every capture group start and end in the original string—ideal for editors, highlighters, and precise replacements.
01
d flag
Indices
02
hasIndices
RegExp prop
03
[start,end)
Position pairs
04
Groups
indices[1]…
05
Named
indices.groups
06
Not \d
Flag vs digit
Fundamentals
Introduction
By default, a successful exec() or match() call gives you the matched text and capture groups, plus an index for the overall match. When you also need the exact start and end position of each capture group, add the d modifier.
The result is an indices array: parallel to the match array, with [start, end) ranges for the full match and every group. This is especially useful when building syntax highlighters, search UIs, or tools that wrap matched text in markup without re-searching the string.
Concept
Understanding the d Modifier
Append d to a regex literal or pass "d" in the constructor flags string. The RegExp instance exposes hasIndices: true, and match results include an indices property.
JavaScript
const re = /(\w+)@(\w+)/d;
const m = re.exec("Contact alice@example.com today");
m[0]; // "alice@example.com"
m[1]; // "alice"
m[2]; // "example.com"
m.indices[0]; // [8, 25] full match range
m.indices[1]; // [8, 13] group 1
m.indices[2]; // [14, 25] group 2
Ranges use half-open intervals: start is inclusive, end is exclusive—the same convention as String.slice(start, end).
💡
Beginner Tip
Do not confuse the dmodifier (indices flag) with the \dmetacharacter (match a digit). The modifier is a trailing flag on the regex; \d appears inside the pattern.
Usage
How to Use the d Modifier
Enable indices on literals, constructors, and combined flag strings:
JavaScript
/hello/d; // literal with d
new RegExp("hello", "d"); // constructor
/cat/gd; // global + indices
re.hasIndices; // true when d is set
m.indices.groups?.year; // named group range
Use exec() for one match, or matchAll() with gd to collect indices for every occurrence in a string.
Foundation
📝 Syntax
JavaScript
/pattern/d // indices on one match
/pattern/gd // indices on every match (with g)
new RegExp("p", "d") // constructor form
re.hasIndices // true | false
result.indices[n] // [start, end) for match index n
result.indices.groups // named capture ranges
Common patterns
/pattern/d — single match with index ranges.
/pattern/gd — all matches with indices via matchAll().
/(?<name>...)/d — named groups in indices.groups.
re.hasIndices — check whether the flag is active.
Cheat Sheet
⚡ Quick Reference
Goal
Pattern / API
Enable indices
/pattern/d
Check flag
regex.hasIndices
Full match range
match.indices[0]
Capture group 1 range
match.indices[1]
Named group range
match.indices.groups.name
All matches + indices
text.matchAll(/p/gd)
Compare
📋 d vs index vs \d vs g
Four related but distinct regex concepts beginners often mix up.
d modifier
/pat/d
Group index ranges
index property
match.index
Start of full match only
\d metachar
\d
Match a digit
g modifier
/pat/g
Find all matches
Hands-On
Examples Gallery
Open DevTools Console (F12) or use Try-it links. Examples cover exec indices, hasIndices, highlighting, named groups, and matchAll with gd.
📚 Getting Started
Read index ranges from a single exec() call.
Example 1 — Capture Group Indices with exec()
Parse an email and read where each part sits in the string.
Named groups appear in both groups (values) and indices.groups (ranges). Handy when different parts of a match need different styling in a UI.
Example 5 — All Matches with matchAll() and gd
Collect index ranges for every occurrence in a string.
JavaScript
const text = "cat dog cat";
const re = /cat/gd;
for (const m of text.matchAll(re)) {
console.log(m[0], "at", m.indices[0]);
}
// "cat" at [0, 3]
// "cat" at [8, 11]
See \d for the digit metacharacter (unrelated to this flag).
Flag order in literals is flexible: /cat/dg and /cat/gd are equivalent.
Compatibility
Browser & Runtime Support
The d (indices / hasIndices) modifier is an ES2022 feature with solid support in current browsers and Node.js.
✓ Baseline · ES2022
RegExp d flag
Supported in modern Chrome, Firefox, Safari, and Node.js 16+. Older environments may omit match.indices.
92%Modern runtimes
Google ChromeSupported · Desktop & Mobile
Full support
Mozilla FirefoxSupported · Desktop & Mobile
Full support
Apple SafariSupported · macOS & iOS
Full support
Microsoft EdgeSupported · Chromium
Full support
Internet ExplorerNo native support · Use a polyfill
Polyfill
OperaSupported · Modern versions
Full support
Samsung InternetSupported · Android
Full support
BunSupported · JavaScript runtime
Supported
DenoSupported · JavaScript runtime
Supported
Node.jsSupported · Server runtime
Supported
Android WebViewSupported · Modern WebView
Full support
dVery good
Bottom line: Safe for modern apps. Feature-detect with regex.hasIndices or check for match.indices before use in legacy targets.
Wrap Up
Conclusion
The d modifier adds an indices property to match results, giving you precise [start, end) ranges for the full match and every capture group. It is the right tool when you need positions—not just matched text.
Remember: d is a flag, not the \d digit metacharacter. Pair it with g for matchAll(), and read named ranges from indices.groups. Next, learn the g global modifier.
Slice with text.slice(start, end) using index ranges
Check hasIndices before assuming indices exists
Use indices.groups for named capture positions
❌ Don’t
Confuse the d modifier with \d digit matching
Assume indices exists without the d flag
Treat end as inclusive (it is exclusive)
Re-search the string when indices already give exact ranges
Expect full support in very old browsers without a fallback
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about the RegExp d modifier
Get exact match and capture group positions in one exec call.
5
Core concepts
📍01
d flag
Indices.
Syntax
📈02
indices[n]
[start,end).
Ranges
🚫03
Not \d
Different.
Compare
🔒04
.groups
Named ranges.
Named
🔢05
gd
matchAll.
Combine
❓ Frequently Asked Questions
The d flag (indices / hasIndices) adds an indices property to match results. Each entry is a [start, end) pair showing where the full match and each capture group appeared in the original string.
No. The d flag is a regex modifier that records match positions. The \d metacharacter matches a digit character. They look similar on paper but serve completely different roles.
Add d to the flags: /pattern/d, /pattern/gd, or new RegExp('pattern', 'd'). The hasIndices property on the RegExp instance becomes true.
indices is an array parallel to the match array. indices[0] is the full match range, indices[1] is capture group 1, and so on. Each value is [start, end) or undefined when a group did not participate.
Not always. A single exec() or match() call works with d alone. Combine gd when you want indices for every match via matchAll() or repeated exec() loops.
The indices flag is part of ES2022. It works in modern Chrome, Firefox, Safari, and Node.js 16+. Older runtimes ignore the flag or lack indices on results.
Did you know?
Before the d flag, getting capture-group positions required re-running indexOf on each group value or walking the string manually. The indices feature lets the engine report all ranges in a single match call—faster and less error-prone for complex patterns.