ValidKit Python SDK
Email validation for signup flows -- block junk without blocking test+staging@example.com. Sync and async clients, batch support up to 10K emails, automatic retries, and Pydantic models.
Installation
pip install validkit
Requires Python 3.8+.
Quick Start
from validkit import ValidKit
client = ValidKit("your_api_key")
result = client.verify("user@example.com")
print(result.v) # True or False
client.close()
Or with a context manager:
from validkit import ValidKit
with ValidKit("your_api_key") as client:
# Single email
result = client.verify("user@example.com")
print(result.v)
# Batch -- compact format by default
results = client.verify_batch([
"alice@company.com",
"bob@tempmail.com",
"not-an-email",
])
for email, r in results.items():
print(f"{email}: valid={r.v}, disposable={r.d}")
Async usage
For high-throughput applications, use AsyncValidKit directly:
import asyncio
from validkit import AsyncValidKit
async def main():
async with AsyncValidKit(api_key="your_api_key") as client:
result = await client.verify_email("user@example.com")
print(result.valid)
asyncio.run(main())
Features
- Sync and async --
ValidKitfor scripts,AsyncValidKitfor high-throughput - Batch verification -- up to 10,000 emails per call, chunked automatically
- Developer Pattern Intelligence -- understands
test@,+addressing, disposable domains - Compact format -- token-efficient responses (
v,d,rfields) enabled by default - Streaming --
async forresults as they complete - Webhook delivery -- fire-and-forget async batch jobs with callback
- Automatic retries -- exponential backoff, 3 retries default
- Type-safe -- Pydantic v2 models with full type hints
Advanced Usage
Custom configuration
from validkit import AsyncValidKit, ValidKitConfig
config = ValidKitConfig(
api_key="your_api_key",
timeout=30, # seconds
max_retries=3, # retry count
max_connections=100, # connection pool size
rate_limit=10000, # requests/min (None = unlimited)
compact_format=True, # smaller payloads
)
async with AsyncValidKit(config=config) as client:
result = await client.verify_email("user@example.com")
Batch with progress tracking
def on_progress(processed, total):
print(f"{processed}/{total} ({processed / total * 100:.1f}%)")
results = await client.verify_batch(
emails,
chunk_size=1000,
progress_callback=on_progress,
)
Async batch with webhook
job = await client.verify_batch_async(
emails=large_list,
webhook_url="https://your-app.com/webhooks/validkit",
webhook_headers={"Authorization": "Bearer token"},
)
# Poll until complete, or wait for webhook
job = await client.get_batch_status(job.id)
results = await client.get_batch_results(job.id)
# Cancel if needed
await client.cancel_batch(job.id)
Streaming
async for email, result in client.stream_verify(emails, batch_size=100):
print(f"{email}: valid={result.v}")
Trace IDs
Attach a trace ID for cross-service debugging:
result = await client.verify_email("user@example.com", trace_id="req_abc123")
Error Handling
from validkit.exceptions import (
ValidKitError, # base -- catches everything
ValidKitAPIError, # API errors (4xx, 5xx)
InvalidAPIKeyError, # 401
RateLimitError, # 429, includes retry_after
BatchSizeError, # batch exceeds 10K
TimeoutError, # request timeout (inherits ValidKitError, not API)
ConnectionError, # network failure (inherits ValidKitError, not API)
)
try:
result = await client.verify_email("user@example.com")
except RateLimitError as e:
print(e.retry_after) # seconds until retry
except InvalidAPIKeyError:
print("Check your API key")
except ValidKitAPIError as e:
print(e.message, e.status_code, e.code)
except ValidKitError as e:
# Catches TimeoutError, ConnectionError, and any other non-API errors
print(f"SDK error: {e}")
The SDK retries automatically on rate limits and transient errors (up to max_retries). Catch exceptions only if you need custom handling.
Compact Response Format
Default format. Smaller payloads, same information:
| Field | Type | Meaning |
|---|---|---|
v |
bool |
Email is valid |
d |
bool | None |
Domain is disposable (None if not checked) |
r |
str | None |
Reason (present only when invalid) |
# Compact (default)
r = await client.verify_email("bad@example.com")
print(r.v, r.d, r.r) # False, False, "invalid_format"
# Full format -- use when you need MX records, SMTP details
from validkit.models import ResponseFormat
full = await client.verify_email("user@example.com", format=ResponseFormat.FULL)
if full.mx:
print(full.mx.records) # ["mx1.example.com"]
Examples
See examples/:
basic_usage.py-- single verification, batch, streaming, configurationbatch_processing.py-- large batches, CSV processing, webhook jobs, domain analysis
Contributing
See CONTRIBUTING.md.
Support
Docs -- GitHub Issues -- developers@validkit.com
License
MIT -- see LICENSE.
Metadata
Release files for validkit 1.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| validkit-1.2.1.tar.gz | 20.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| validkit-1.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.1 kB
Release files / validkit-1.2.1.tar.gz
| Download URL | validkit-1.2.1.tar.gz |
|---|---|
| Size | 20.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8853d09988c18273f1a71b92a7fc46682d5879ad822e5041f22c6f492a725688
|
|
BLAKE2b-256 checksum How to use checksums |
dcca48dedbac9eff816288de4d1bc1356b5fd49c6cddbd6a692efd199a940199
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.6
|
Release files / validkit-1.2.1-py3-none-any.whl
| Download URL | validkit-1.2.1-py3-none-any.whl |
|---|---|
| Size | 22.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e57635e94654657ab4549b357ade9de4c710f2a83c53c72c8056f279975af2d4
|
|
BLAKE2b-256 checksum How to use checksums |
6f934bf17fe7cd713d407884d6283c8c1c546f1e8a755d63a75b2a5a519c0fb7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.6
|