# Regex ^ Meaning in Python: Start Anchors, Multiline Mode, and Character Class Negation

> Master regex ^ meaning in Python. Learn about start anchors, multiline mode, and character class negation with clear examples. Improve your Python regex skills today.

- Repository: [Python/cpython](https://github.com/python/cpython)
- Tags: tutorial
- Published: 2026-02-16

---

**The caret (`^`) in Python regex serves as a start-of-string anchor by default, matches the start of each line when the `re.MULTILINE` flag is set, and negates character classes when placed first inside square brackets.**

Understanding the regex ^ meaning is essential for writing precise pattern-matching logic in Python. In the `python/cpython` repository, the `re` module implements these behaviors in [`Lib/re/__init__.py`](https://github.com/python/cpython/blob/main/Lib/re/__init__.py) and [`Lib/re/_parser.py`](https://github.com/python/cpython/blob/main/Lib/re/_parser.py), providing three distinct functionalities depending on context.

## The Three Roles of the Caret in Python Regex

The caret operator is context-sensitive. According to the CPython source code, it functions as:

- A **start-of-string anchor** when appearing outside character classes
- A **multiline line-start anchor** when the `re.MULTILINE` flag is active
- A **negation operator** when positioned as the first character inside a character class `[...]`

## Start-of-String Anchor Behavior

When used outside square brackets, `^` matches the position immediately before the first character of the string. The module documentation in [`Lib/re/__init__.py`](https://github.com/python/cpython/blob/main/Lib/re/__init__.py) (lines 30-33) explicitly defines this as matching "the beginning of the string."

```python
import re

text = "hello world"

# ^hello matches only if "hello" is at the very start

match = re.search(r'^hello', text)
print(bool(match))  # True

```

If the pattern appears later in the string, the anchor prevents a match:

```python
text = "say hello world"
match = re.search(r'^hello', text)
print(bool(match))  # False

```

## Multiline Mode: Matching the Start of Every Line

The regex ^ meaning expands when you enable **multiline mode** using the `re.MULTILINE` flag (or `re.M`). As documented in [`Lib/re/__init__.py`](https://github.com/python/cpython/blob/main/Lib/re/__init__.py) (lines 112-114), this flag modifies `^` to also match immediately after each newline character, effectively treating each line as its own string for anchoring purposes.

```python
multiline_text = "first line\nsecond line\nthird line"

# Without MULTILINE, ^ only matches the very beginning

pattern_single = re.compile(r'^second')
print(bool(pattern_single.search(multiline_text)))  # False

# With MULTILINE, ^ matches after each \n

pattern_multi = re.compile(r'^second', re.MULTILINE)
print(bool(pattern_multi.search(multiline_text)))  # True

```

This behavior is particularly useful when processing log files or CSV data where you need to validate patterns at the start of individual records.

## Negating Character Classes with ^

Inside a character class `[...]`, the regex ^ meaning shifts entirely to **negation**. When `^` appears as the first character within the brackets, it inverts the set, matching any character *not* listed. This is documented in [`Lib/re/__init__.py`](https://github.com/python/cpython/blob/main/Lib/re/__init__.py) (lines 42-44) and implemented in the parser at [`Lib/re/_parser.py`](https://github.com/python/cpython/blob/main/Lib/re/_parser.py) (lines 562-567).

```python

# Match any character that is NOT a digit

non_digits = re.findall(r'[^0-9]', 'abc123')
print(non_digits)  # ['a', 'b', 'c']

# Match any character that is NOT a vowel

consonants = re.findall(r'[^aeiou]', 'hello')
print(consonants)  # ['h', 'l', 'l']

```

If `^` appears anywhere other than the first position inside brackets, it loses its special meaning and matches a literal caret character:

```python

# ^ is literal here, not negation

literal_caret = re.findall(r'[a^b]', 'a^b')
print(literal_caret)  # ['a', '^', 'b']

```

## Combining Anchors and Negated Classes

You can combine these behaviors to create sophisticated patterns. For example, finding lines that begin with a non-digit character requires both the multiline anchor and a negated character class:

```python
text = "1one\n2two\nthree\n4four"

# Lines starting with a non-digit

lines = re.findall(r'^[^0-9].*', text, re.MULTILINE)
print(lines)  # ['three']

```

The first `^` anchors to the start of the line (enabled by `re.MULTILINE`), while `[^0-9]` ensures the first character is not a numeric digit.

## Summary

- The caret (`^`) functions as a **start-of-string anchor** by default, matching the position before the first character.
- With the **`re.MULTILINE`** flag, `^` also matches after every newline, enabling line-by-line validation.
- Inside character classes (`[...]`), a leading `^` **negates** the set, matching any character not listed.
- These behaviors are implemented in [`Lib/re/__init__.py`](https://github.com/python/cpython/blob/main/Lib/re/__init__.py) and [`Lib/re/_parser.py`](https://github.com/python/cpython/blob/main/Lib/re/_parser.py) within the CPython repository.

## Frequently Asked Questions

### What is the difference between ^ and $ in Python regex?

The caret (`^`) matches the **start** of a string (or line in multiline mode), while the dollar sign (`$`) matches the **end** of a string (or line). Both are zero-width assertions that do not consume characters, serving as positional anchors rather than matching actual text.

### Why does ^ not work as expected with re.search()?

The `^` anchor works correctly with `re.search()`, but it only matches if the pattern appears at the beginning of the string. If you need to find a pattern at the start of any line within a multi-line string, you must pass the **`re.MULTILINE`** flag to the compilation or search function.

### How do I match lines that do not start with a specific character?

Combine the multiline anchor with a negated character class. Use the pattern `^[^X]` where `X` is the character you want to exclude, and include the `re.MULTILINE` flag. For example, `^[^#]` matches lines that do not start with a hash symbol.

### Does ^ have special meaning inside re.findall()?

The `^` character behaves the same way inside `re.findall()` as it does in any other `re` module function. It anchors to the start of the string (or lines in multiline mode) and acts as a negation operator when placed first inside a character class. The function does not change the fundamental regex ^ meaning.