# Regex para CEP, telefone e e-mail no Brasil

> Uma expressão regular confere o formato de um valor, não se ele existe. Este guia traz expressões para CEP, telefone brasileiro com DDD (celular e fixo) e e-mail, explica cada parte e mostra as armadilhas de Python e PHP que deixam passar uma quebra de linha no fim ou dígitos de outros alfabetos.

- Endereço oficial: https://pradev.com.br/guias/regex-cep-telefone-email
- Tipo: Guia
- Publicado em: 2026-09-30
- Atualizado em: 2026-09-30
- Autor: Leonardo Gaertner (https://pradev.com.br/sobre)
- Ferramentas: [Testador de Regex](https://pradev.com.br/regex-tester)

## Formato não é existência

Uma regex diz se `01310-100` tem cara de CEP, não se o CEP existe. Para existência, consulte uma base de CEPs, envie um SMS de confirmação ou um e-mail com link. Use a regex para barrar erros de digitação cedo, antes de ir ao servidor.

Para testar cada expressão com seus próprios exemplos, cole no [testador de regex](https://pradev.com.br/regex-tester).

## As expressões, parte por parte

### CEP

`^\d{5}-?\d{3}$`: cinco dígitos, hífen opcional e três dígitos. Aceita `01310-100` e `01310100`.

### Telefone com DDD

- `\(?[1-9]{2}\)?`: o DDD, com parênteses opcionais. Nenhum DDD brasileiro tem o dígito zero.
- `9\d{4}`: celular, com o 9 na frente e mais quatro dígitos antes do hífen.
- `[2-5]\d{3}`: telefone fixo, que começa de 2 a 5.
- `-?\d{4}`: hífen opcional e os quatro últimos dígitos.

Ela aceita `(11) 91234-5678`, `11912345678` e `(11) 3123-4567`. Com `+55` na frente, remova o código do país antes de validar.

### E-mail

`^[^\s@]+@[^\s@]+\.[^\s@]+$`: algo, arroba, algo, ponto, algo, sem espaços. A especificação de e-mail permite formatos que quase ninguém usa, e regex maiores costumam recusar endereços válidos. Uma checagem simples mais um e-mail de confirmação é o caminho seguro.

## Em JavaScript

No JavaScript, sem a flag `m`, o `$` só combina no fim do texto, então as expressões funcionam como estão:

```javascript
// CEP: 5 dígitos, hífen opcional e 3 dígitos
const reCEP = /^\d{5}-?\d{3}$/;
// Telefone com DDD: celular (9 + 8 dígitos) ou fixo (começa de 2 a 5)
const reTelefone = /^\(?[1-9]{2}\)? ?(?:9\d{4}|[2-5]\d{3})-?\d{4}$/;
// E-mail: só confere o formato geral. A prova real é enviar um e-mail de confirmação.
const reEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

const cepValido = (v) => reCEP.test(v);
const telefoneValido = (v) => reTelefone.test(v);
const emailValido = (v) => reEmail.test(v);
```

_JavaScript_

## Em Python: fullmatch e re.ASCII

Duas armadilhas. Em Python, o `$` também combina antes de uma quebra de linha no fim, então `^\d{8}$` aceita `"01310100\n"`: use `fullmatch`. E o `\d` aceita dígitos de outros alfabetos, como os arábicos `٠١٣`: use `re.ASCII`.

```python
import re

# re.ASCII: sem ele, \d também aceita dígitos de outros alfabetos, como ٣
RE_CEP = re.compile(r"\d{5}-?\d{3}", re.ASCII)
RE_TELEFONE = re.compile(r"\(?[1-9]{2}\)? ?(?:9\d{4}|[2-5]\d{3})-?\d{4}", re.ASCII)
RE_EMAIL = re.compile(r"[^\s@]+@[^\s@]+\.[^\s@]+")


# fullmatch exige que o texto inteiro combine (o $ aceitaria uma quebra de linha no fim)
def cep_valido(v: str) -> bool:
    return RE_CEP.fullmatch(v) is not None


def telefone_valido(v: str) -> bool:
    return RE_TELEFONE.fullmatch(v) is not None


def email_valido(v: str) -> bool:
    return RE_EMAIL.fullmatch(v) is not None
```

_Python_

## Em PHP: o modificador D

No PHP, o `$` tem o mesmo comportamento do Python. O modificador `D` no fim da expressão faz o `$` exigir o fim real do texto:

```php
<?php
// O modificador D faz o $ recusar uma quebra de linha no fim do texto
const RE_CEP = '/^\d{5}-?\d{3}$/D';
const RE_TELEFONE = '/^\(?[1-9]{2}\)? ?(?:9\d{4}|[2-5]\d{3})-?\d{4}$/D';
const RE_EMAIL = '/^[^\s@]+@[^\s@]+\.[^\s@]+$/D';

function cepValido(string $v): bool
{
    return preg_match(RE_CEP, $v) === 1;
}

function telefoneValido(string $v): bool
{
    return preg_match(RE_TELEFONE, $v) === 1;
}

function emailValido(string $v): bool
{
    return preg_match(RE_EMAIL, $v) === 1;
}
```

_PHP_

## Cuidados

- Use sempre as âncoras `^` e `$` (ou `fullmatch`). Sem elas, `abc01310-100xyz` passa, porque tem um CEP no meio.
- Guarde telefone e CEP só com dígitos e aplique a máscara na exibição. Isso evita comparar `(11) 91234-5678` com `11912345678` como valores diferentes.
- Valide no servidor também. A validação no navegador ajuda quem digita, mas qualquer pessoa consegue enviar dados sem passar por ela.
- Para CPF e CNPJ, a regex não basta: o formato pode estar certo e o dígito verificador errado. Veja o [guia de validação de CPF](https://pradev.com.br/guias/como-validar-cpf-em-javascript).

## Perguntas frequentes

### Qual a regex para CEP?

Uma opção simples e segura é ^\d{5}-?\d{3}$, que aceita o CEP com e sem hífen. Em Python, use com fullmatch e re.ASCII. Em PHP, acrescente o modificador D.

### Como validar celular brasileiro com regex?

O celular tem DDD de dois dígitos sem zero, o 9 na frente e mais oito dígitos. A expressão deste guia aceita o celular e o fixo, com ou sem parênteses, espaço e hífen.

### Existe uma regex perfeita para e-mail?

Não na prática. A especificação permite formatos raros, e expressões muito grandes acabam recusando endereços válidos ou aceitando inválidos. Confira o formato geral e confirme com um e-mail.

### Por que minha regex aceita um valor com quebra de linha no fim?

Em Python e PHP, o cifrão também combina antes de uma quebra de linha final. Use fullmatch no Python e o modificador D no PHP.

## Fontes

- [MDN: expressões regulares](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Regular_expressions)
- [Python: módulo re](https://docs.python.org/3/library/re.html)

## Guias relacionados

- [Como validar CPF em JavaScript, Python e PHP](https://pradev.com.br/guias/como-validar-cpf-em-javascript): Aprenda a calcular os dígitos verificadores do CPF e veja funções prontas e testadas para validar CPF em JavaScript, Python e PHP.
