How-to Guide 6 min read

Regex Works in the Tester but Not in My Code? 6 Reasons and Fixes

A regex that matches in a tester but fails in JavaScript, Python or Java usually has lost backslashes, different flags or engine differences. How to fix it.

regex works in tester but not in coderegex not working in javascriptpython regex raw stringregex backslash escaperegex global flag lastindex

The short answer

A regex that works in a tester but fails in your code is almost never a wrong pattern. It is usually one of four things: backslashes eaten by your programming language's string rules, missing or different flags, a regex engine that does not support a feature (Python, for example, uses (?P<name>...) for named groups), or a global regex being reused between calls. The Regex Tester uses JavaScript's own regex engine, so a pattern that works there will work in JavaScript once it is written into your code correctly.

What the tester actually runs

Before debugging, it helps to know exactly what you tested:

  • Pattern box: you type the raw pattern, without slashes, for example \d{4}-\d{2}. It is passed to JavaScript's new RegExp(pattern, flags) as typed, so you never need to double the backslashes there.
  • Flags box: up to six letters, for example g, gi or gm. With g, every match is listed; without it, only the first.
  • Results: each match is highlighted in the test string, and capture groups are listed under each match.

So the tester shows how a pattern behaves in JavaScript with those exact flags. Everything below is about what changes when you move it into real code.

Cause 1: Backslashes disappear inside strings

This is the most common reason. In most languages, a backslash inside a normal string starts an escape sequence, so the string loses it before the regex engine ever sees it.

In JavaScript, if you build the regex from a string:

  • new RegExp("\d+") becomes the pattern d+, which matches the letter d. Running it on "a1d" matches "d", not "1".
  • new RegExp("\\d+") becomes \d+, which matches digits as intended.

Fixes for each language:

LanguageWrite the pattern as
JavaScript (literal)/\d+/ (no doubling needed)
JavaScript (string)new RegExp("\\d+")
Pythonr"\d+" (raw string)
Java, C#, Go (normal strings)"\\d+"
C# verbatim string@"\d+"
Go raw stringa backtick-quoted string, with single backslashes
JSON config files"\\d+"

In Python, always use raw strings (r"...") for regex. Recent Python versions warn about "\d" in a normal string, and some escapes such as "\b" silently turn into a different character (a backspace), so a word-boundary pattern stops matching without any error.

Quick test: print the pattern from your code (console.log(re.source) in JavaScript, print(pattern) in Python). If the printed pattern does not look exactly like what you typed in the tester, the string escaping is the problem.

Cause 2: Different flags

The flags box in the tester is easy to forget. Common mismatches:

  • Case: "Hello hello" with pattern hello finds one match, but two with the i flag.
  • Start and end of line: ^ and $ match the start and end of the whole text unless the m (multiline) flag is on. On "line1" followed by "line2" on the next line, ^line2$ finds nothing without m, and matches with it.
  • Dot and new lines: . does not match a line break unless you use the s flag. a.b does not match "a", line break, "b" without it.
  • All matches: in JavaScript, "text".match(/x/) returns the first match only; you need the g flag (or matchAll) for all of them.

Python spells flags differently: re.I, re.M and re.S, passed as an argument, for example re.findall(r"^line2$", text, re.M).

Cause 3: The other language's regex engine is different

Regex is not one standard. JavaScript, Python, Java, .NET, PHP (PCRE) and Go each support slightly different features. A pattern tested in JavaScript can fail elsewhere, and vice versa.

FeatureJavaScriptPython re
Named group(?<year>\d{4})(?P<year>\d{4})
Lookbehind whose alternatives differ in length ("$" or "USD ")WorksError: needs fixed width
Flag for dot matches new linesre.S

We checked both rows in Python 3.13: (?<year>...) raises "unknown extension", and the alternating lookbehind raises "look-behind requires fixed-width pattern". The same patterns work in JavaScript.

Other engines have their own limits. Go's standard regexp package, for example, does not support lookarounds or backreferences at all. If you are not writing JavaScript, test the final pattern in your target language before relying on it.

Cause 4: A reused global regex in JavaScript

A JavaScript regex with the g flag remembers where its last match ended (its lastIndex). If you call .test() repeatedly with the same regex object, results alternate:

const r = /cat/g; then r.test("cat") three times returns true, false, true.

The second call starts searching after the first match, finds nothing, and resets. This causes validation code that passes one input and fails the next identical one.

Fix: remove the g flag when you only want a yes/no answer, or create the regex inside the function so it starts fresh each time.

Cause 5: The test string is not the real input

The tester only sees what you paste. Real input may differ:

  • Windows line endings: text from files may have a carriage return before each line break, so $ sits after an invisible character. Use \r?$ or strip the \r first.
  • Leading or trailing spaces: a form value " 560001 " fails ^\d{6}$. Trim input before matching.
  • Unicode look-alikes: curly quotes, non-breaking spaces and full-width digits do not match ', or \d patterns written for plain ASCII text.
  • Whole string versus part: \d{6} finds six digits anywhere, so "1234567" passes. Use ^\d{6}$ for an exact match. The guide to regex for Indian mobile numbers, PIN codes and PAN has anchored, tested examples.

Cause 6: You are replacing, not matching

If matching works but the replacement output is wrong, check the replacement syntax. JavaScript uses $1 for group 1 and $<name> for named groups. Python uses \1 or \g<name>. To try replacements before writing code, use Find and Replace with Use regex ticked; it uses the same JavaScript $1 syntax. For more on groups, see find and replace with regex capture groups.

A debugging routine that works

  • Print the pattern exactly as your code sees it, after string escaping.
  • Paste that printed pattern into the tester, not the one you think you wrote.
  • Copy the flags from your code into the flags box.
  • Paste real input from your logs, including line breaks and spaces.
  • If it matches in the tester but not in your code and you are not using JavaScript, look up the feature in your language's regex documentation.
  • Your pattern and test text stay in your browser; nothing is sent to a server.

    Frequently asked questions

    Why does my regex work online but not in my code?

    Usually because your programming language removed backslashes from the string, the flags differ, or the language's regex engine does not support a feature. Print the pattern from your code and test that exact text.

    Do I need to double backslashes in a regex?

    Only when the pattern is inside a normal string, such as new RegExp("\\d+") in JavaScript or "\\d+" in Java. Regex literals like /\d+/ and Python raw strings like r"\d+" need single backslashes.

    Why does my JavaScript regex test() return true then false?

    A regex with the g flag remembers where the last match ended. Calling test() again on the same object starts from there. Remove the g flag for yes/no checks or create the regex each time.

    Are named groups the same in Python and JavaScript?

    No. JavaScript uses (?<name>...), while Python's re module uses (?P<name>...). Python 3.13 rejects the JavaScript form with an unknown extension error.

    Which regex engine does the Lazyblink Regex Tester use?

    It uses your browser's JavaScript regex engine, so results match JavaScript code that uses the same pattern and flags.

    Try this tool on Lazyblink

    Put this guide into practice with our free online tool — no signup required.

    Open tool