# Look up an email address

One call tells you whether an address will accept mail. Use it at signup, or over a list you are about to import, to keep addresses that would bounce out of your sending in the first place. Everything here needs an API key with the `lookup` scope.

## Look up an address

<!-- bird:tabs typescript,python,go,php,cli,curl -->

<!-- bird:snippet lookup.email -->

```typescript
const answer = await bird.lookup.email({ email: "aisha.khan@example.com" });
// result is an open vocabulary; delivery_confidence is always comparable.
console.log(answer.result, answer.delivery_confidence);
```

<!-- bird:snippet lookup.email -->

```python
answer = client.lookup.email(email="aisha.khan@example.com")
# result is an open vocabulary; delivery_confidence is always comparable.
print(answer.result, answer.delivery_confidence)
```

<!-- bird:snippet lookup.email -->

```go
answer, err := client.Lookup.Email(context.Background(), bird.LookupEmailParams{
	Email: "aisha.khan@example.com",
})
if err != nil {
	log.Fatal(err)
}
// result is an open vocabulary; delivery_confidence is always comparable.
fmt.Println(*answer.Result, *answer.DeliveryConfidence)
```

<!-- bird:snippet lookup.email -->

```php
$answer = $bird->lookup->email(
    (new EmailLookupRequest())->setEmail('aisha.khan@example.com'),
);
// result is an open vocabulary; delivery_confidence is always comparable.
echo $answer->getResult(), ' ', $answer->getDeliveryConfidence();
```

```bash
bird lookup email --email aisha.khan@example.com
```

```bash
curl -X POST "https://us1.platform.bird.com/v1/lookup/email" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "aisha.khan@example.com"
  }'
```

<!-- /bird:tabs -->

## How to write the address

Send a bare address, exactly as you hold it. A display-name form such as `Aisha <aisha@example.com>` is rejected rather than unwrapped, because unwrapping it would look up an address you did not send.

The part before the `@` is case-sensitive per the mail standards, so it is never lowercased. `Aisha.Khan@example.com` and `aisha.khan@example.com` are different addresses and are looked up as written.

## The five verdicts

`result` is the field to decide on.

`valid`: the address exists and accepts mail. Send.

`neutral`: it could not be confirmed either way, usually because the receiving domain answers every recipient the same way. Sending is reasonable; a neutral address is not a bad address, it is an unanswerable one.

`risky`: it probably accepts mail but is likelier than most to bounce or complain. Role addresses, disposable addresses and low-reputation addresses land here. Whether to send is a judgement about your own tolerance for complaints, and `flags` tells you which kind of risk it is.

`undeliverable`: it does not accept mail. Do not send. `reason` says why: `invalid_syntax` for a malformed address, `invalid_domain` when the domain does not accept mail at all, `invalid_recipient` when the domain accepts mail but this mailbox does not exist.

`typo`: the address looks misspelled, and `did_you_mean` carries the correction. Offer the correction to whoever typed the original rather than sending to it unasked: it is a guess, and the address they meant may be neither one.

`result` is an open vocabulary, so a value you do not recognize is a future verdict rather than an error. Branch on the values you know and fall back on `delivery_confidence`, which is always present and always comparable.

## Read confidence alongside the verdict, not instead of it

`delivery_confidence` runs from 0 (certain not to be delivered) to 100 (certain to be). The same score can sit under `neutral` or `risky` for different reasons, so it is a second opinion rather than a replacement for `result`. It is the field to lean on when you want one threshold across every verdict, including verdicts added later.

`valid` is a separate, narrower field: it says whether the address is well-formed and its domain is set up to receive mail at all. It says nothing about the mailbox, so an address with a working domain and no such mailbox is `true` here and `undeliverable` in `result`.

## Flags describe the kind of address

`flags` is empty when nothing notable applies. Three values are defined today, and it is an open list.

`role` means the address names a function rather than a person, such as `support@` or `info@`. Replies and consent are ambiguous, and complaints are likelier.

`disposable` means it belongs to a throwaway-address provider, so it will typically stop existing.

`free_provider` means it belongs to a consumer mailbox provider such as Gmail or Outlook.com. That is ordinary for consumer mail, and a signal only when you expected a business address.

## Retry without paying twice

Every answered address is billed, `undeliverable` included, because that is the answer you paid for and the bounce you avoided. Send an `Idempotency-Key` so a retry replays the stored verdict instead of buying a second one. See [Idempotency](/docs/guides/idempotency).

The `GET` form, which puts the address in the URL, cannot carry an idempotency key. Use the `POST` form for anything automated.

## Errors

| Code                                | What happened                                                                                |
| ----------------------------------- | -------------------------------------------------------------------------------------------- |
| [`E22003`](/docs/api/errors/E22003) | The address is not a valid email address. Nothing was charged.                               |
| [`E22001`](/docs/api/errors/E22001) | The organization's wallet cannot cover the lookup. Top it up and retry. Nothing was charged. |
| [`E22002`](/docs/api/errors/E22002) | Lookup is temporarily unavailable. Retry with backoff. Nothing was charged.                  |

## Next steps

- [Look up a phone number](/docs/guides/lookup/phone-numbers) is the other half of Lookup.
- [Suppressions](/docs/guides/email/suppressions) stop repeat sends to addresses that already bounced, at no cost.
- [Lookup API reference](/docs/api/reference/create-email-lookup) documents every field.