Detect disposable, temporary, and throwaway email addresses in real time with a simple Python client for the isitdisposable.com API.
Project description
isitdisposable
Detect disposable, temporary, and burner email addresses in real time from Python, using the isitdisposable.com Application Programming Interface (API).
Install
pip install isitdisposable
or with uv:
uv add isitdisposable
You will need an API key from isitdisposable.com. A free tier is available, so you can try this out without a credit card.
Quick start: check an email address
from isitdisposable import Client
client = Client(api_key="isid_live_your_key_here")
result = client.check(email="someone@example.com")
if result.disposable:
print("This looks like a disposable email address.")
else:
print("This looks like a real, ongoing email address.")
api_key can also come from the ISITDISPOSABLE_API_KEY environment variable, so in most setups you can just write Client().
Example: block disposable signups in a Django form
# forms.py
from django import forms
from isitdisposable import Client
client = Client() # reads ISITDISPOSABLE_API_KEY from the environment
class SignupForm(forms.Form):
email = forms.EmailField()
def clean_email(self):
email = self.cleaned_data["email"]
result = client.check(email=email)
if result.disposable:
raise forms.ValidationError(
"Please sign up with an email address you check regularly. "
"Disposable or throwaway addresses are not allowed."
)
return email
Example: block disposable signups in a FastAPI dependency
# dependencies.py
from fastapi import Depends, HTTPException
from isitdisposable import AsyncClient
async_client = AsyncClient() # reads ISITDISPOSABLE_API_KEY from the environment
async def reject_disposable_email(email: str) -> str:
result = await async_client.check(email=email)
if result.disposable:
raise HTTPException(
status_code=400,
detail="Please use an email address you check regularly, not a disposable one.",
)
return email
# In a route:
# @app.post("/signup")
# async def signup(email: str = Depends(reject_disposable_email)):
# ...
Checking a batch
Check up to 100 emails or domains in a single request. Items can be plain strings (anything containing an "@" is treated as an email, everything else as a domain) or dicts:
result = client.check_batch(
[
"someone@example.com",
"example.org",
{"domain": "another-example.com"},
]
)
for item in result.results:
print(item.domain, item.disposable, item.action)
print(f"Checked {result.count} items.")
Fail open by design
Signup forms and checkout flows should never break because of an email checking service having a bad moment. This client fails open by default: if the isitdisposable.com service cannot be reached, times out, is rate limiting you, or has an internal error, check() and check_batch() do not raise. Instead they return a result where checked is False, disposable is None, and action is "allow", and a warning is logged through the standard logging module under the logger name "isitdisposable". Your form keeps working; you can watch the warning logs to notice if this starts happening a lot.
If you would rather see failures as exceptions (for example in a background job where you want to retry later), turn this off:
client = Client(fail_open=False)
With fail_open=False, a connection problem raises NetworkError, a rate limit response raises RateLimitError, and a server error raises ServerError. Invalid requests (a missing or malformed API key, or a request that is missing both an email and a domain) always raise, in either mode, because those indicate something in your own code needs fixing rather than a temporary service problem.
Response fields
Every check returns a result with these fields. Any field can be None if the underlying signal was not evaluated for that request.
| Field | Type | Meaning |
|---|---|---|
checked |
bool |
Whether a real check was performed (False on a fail-open response). |
normalized_email |
str or None |
The email address you sent, normalized. |
domain |
str or None |
The domain that was evaluated. |
disposable |
bool or None |
The core verdict: whether the domain is a disposable or throwaway email provider. |
mx_valid |
bool or None |
Whether the domain has a working mail server. |
role_account |
bool or None |
Whether the local part looks like a role address (for example support@). |
relay |
bool or None |
Whether the domain is a mail relay or forwarding service. |
public_domain |
bool or None |
Whether the domain is a large public provider (for example a well known free email service). |
spam_risk |
bool or None |
Whether the domain appears on a spam or abuse reputation list. Only populated if your account has this signal enabled. |
mx_masked |
bool or None |
Whether the domain's mail server is masked or hidden behind a routing service. |
did_you_mean |
str or None |
A suggested correction if the domain looks like a likely typo. |
mx_records |
list[str] or None |
The mail server records found for the domain. |
action |
str |
The recommended action for your account's policy: "allow", "warn", or "block". |
reason |
str or None |
A machine readable reason code. This set is open ended; treat unknown values as informational. |
raw |
dict |
The full parsed response, including any fields not yet listed above, for forward compatibility. |
Links
- Website: https://isitdisposable.com
- Documentation: https://isitdisposable.com/docs
- A free tier is available, so you can get started without a credit card.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file isitdisposable-0.1.1.tar.gz.
File metadata
- Download URL: isitdisposable-0.1.1.tar.gz
- Upload date:
- Size: 26.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
24d334c846a6a6aeb03ef0354dbe5288e2e50028be409033ee4e664137690866
|
|
| MD5 |
9048ec08c5b77eec003241095ce3a04b
|
|
| BLAKE2b-256 |
c9510b8708d28770a93dd9640c05af1dab32b30c80f770c45d10f87d93563673
|
File details
Details for the file isitdisposable-0.1.1-py3-none-any.whl.
File metadata
- Download URL: isitdisposable-0.1.1-py3-none-any.whl
- Upload date:
- Size: 14.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df6c31570fc5906424b1c1be46be0609150b3af65f37b07aee33bcae3be742f9
|
|
| MD5 |
a62add305b8b829e8dea6159a5bc7c82
|
|
| BLAKE2b-256 |
0762f7e149c46b205f13adea1f4a26e65432b5bd91fb284094933ea7eb86f00d
|