Main
Email Verification API Guide
Everything in one place: ready-to-run tutorials in your language, your live credits balance, and a complete response field reference.
Quick request
https://api.validemail.net/?email=EMAIL_ADDRESS&token=YOUR_API_KEY
Replace EMAIL_ADDRESS and YOUR_API_KEY with your real values, or sign in to get a personalized URL.
Integration Tutorials
Pick your language and copy the complete, best-practice integration: it verifies an address,
automatically retries interim Unknown results, and applies the recommended
Score ≥ 80 sending rule.
The fastest way to try the API — run these straight from your terminal.
Verify one address
curl "https://api.validemail.net/?email=someone@example.com&token=YOUR_API_KEY"
Check your credits balance (free)
curl "https://api.validemail.net/balance?token=YOUR_API_KEY"
1 · Install the dependency
pip install requests
2 · Verify an email address
import time
import requests
API_URL = "https://api.validemail.net/"
API_KEY = "YOUR_API_KEY"
def verify_email(email: str, max_retries: int = 3) -> dict:
"""Verify an email address, retrying while the result is still pending."""
for _ in range(max_retries):
response = requests.get(API_URL, params={"email": email, "token": API_KEY}, timeout=90)
response.raise_for_status()
result = response.json()
# "Unknown" means the verification is still in progress (e.g. greylisting).
retry_after = result.get("RetryAfterSeconds")
if result["State"] == "Unknown" and retry_after:
time.sleep(retry_after)
continue
return result
return result # still pending after max_retries — treat as risky
result = verify_email("someone@example.com")
print(f"Valid: {result['IsValid']}")
print(f"Score: {result['Score']}")
print(f"State: {result['State']}")
print(f"Reason: {result['Reason']}")
if result["IsValid"] and result["Score"] >= 80:
print("Safe to send.")
3 · Check your credits balance (free)
balance = requests.get(
"https://api.validemail.net/balance",
params={"token": API_KEY},
timeout=30,
).json()["balance"]
print(f"Credits remaining: {balance}")
Uses the built-in fetch API — no dependencies (Node.js 18+).
Run server-side only so your API key stays private.
1 · Verify an email address
const API_URL = 'https://api.validemail.net/';
const API_KEY = 'YOUR_API_KEY';
const sleep = (seconds) => new Promise((resolve) => setTimeout(resolve, seconds * 1000));
async function verifyEmail(email, maxRetries = 3) {
let result;
for (let attempt = 0; attempt < maxRetries; attempt++) {
const params = new URLSearchParams({ email, token: API_KEY });
const response = await fetch(`${API_URL}?${params}`);
if (!response.ok) {
throw new Error(`Request failed: ${response.status} ${await response.text()}`);
}
result = await response.json();
// "Unknown" means the verification is still in progress (e.g. greylisting).
if (result.State === 'Unknown' && result.RetryAfterSeconds) {
await sleep(result.RetryAfterSeconds);
continue;
}
return result;
}
return result; // still pending after maxRetries — treat as risky
}
const result = await verifyEmail('someone@example.com');
console.log(`Valid: ${result.IsValid}`);
console.log(`Score: ${result.Score}`);
console.log(`State: ${result.State}`);
console.log(`Reason: ${result.Reason}`);
if (result.IsValid && result.Score >= 80) {
console.log('Safe to send.');
}
2 · Check your credits balance (free)
const response = await fetch(`https://api.validemail.net/balance?token=${API_KEY}`);
const { balance } = await response.json();
console.log(`Credits remaining: ${balance}`);
Plain PHP with cURL — works in any framework, from Laravel to WordPress.
1 · Verify an email address
<?php
const API_URL = 'https://api.validemail.net/';
const API_KEY = 'YOUR_API_KEY';
function verifyEmail(string $email, int $maxRetries = 3): array
{
$result = [];
for ($attempt = 0; $attempt < $maxRetries; $attempt++) {
$url = API_URL . '?' . http_build_query(['email' => $email, 'token' => API_KEY]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 90);
$body = curl_exec($ch);
if ($body === false) {
throw new RuntimeException('Request failed: ' . curl_error($ch));
}
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($status !== 200) {
throw new RuntimeException("Request failed with HTTP {$status}: {$body}");
}
$result = json_decode($body, true);
// "Unknown" means the verification is still in progress (e.g. greylisting).
if ($result['State'] === 'Unknown' && !empty($result['RetryAfterSeconds'])) {
sleep($result['RetryAfterSeconds']);
continue;
}
return $result;
}
return $result; // still pending after $maxRetries — treat as risky
}
$result = verifyEmail('someone@example.com');
echo 'Valid: ' . ($result['IsValid'] ? 'yes' : 'no') . PHP_EOL;
echo 'Score: ' . $result['Score'] . PHP_EOL;
echo 'State: ' . $result['State'] . PHP_EOL;
echo 'Reason: ' . $result['Reason'] . PHP_EOL;
if ($result['IsValid'] && $result['Score'] >= 80) {
echo 'Safe to send.' . PHP_EOL;
}
2 · Check your credits balance (free)
$balance = json_decode(
file_get_contents('https://api.validemail.net/balance?token=' . API_KEY),
true
)['balance'];
echo "Credits remaining: {$balance}" . PHP_EOL;
Modern .NET with HttpClient and System.Text.Json — no external packages (.NET 6+).
1 · Verify an email address
using System.Net.Http.Json;
const string ApiUrl = "https://api.validemail.net/";
const string ApiKey = "YOUR_API_KEY";
using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(90) };
var result = await VerifyEmailAsync("someone@example.com");
Console.WriteLine($"Valid: {result.IsValid}");
Console.WriteLine($"Score: {result.Score}");
Console.WriteLine($"State: {result.State}");
Console.WriteLine($"Reason: {result.Reason}");
if (result.IsValid && result.Score >= 80)
{
Console.WriteLine("Safe to send.");
}
async Task<VerificationResult> VerifyEmailAsync(string email, int maxRetries = 3)
{
VerificationResult? result = null;
for (var attempt = 0; attempt < maxRetries; attempt++)
{
var url = $"{ApiUrl}?email={Uri.EscapeDataString(email)}&token={ApiKey}";
result = await client.GetFromJsonAsync<VerificationResult>(url)
?? throw new InvalidOperationException("Empty response.");
// "Unknown" means the verification is still in progress (e.g. greylisting).
if (result.State == "Unknown" && result.RetryAfterSeconds is int retryAfter)
{
await Task.Delay(TimeSpan.FromSeconds(retryAfter));
continue;
}
return result;
}
return result!; // still pending after maxRetries — treat as risky
}
public sealed record VerificationResult(
bool IsValid,
int Score,
string Email,
string State,
string Reason,
string Domain,
bool Free,
bool Role,
bool Disposable,
bool AcceptAll,
bool Tag,
string MXRecord,
int? RetryAfterSeconds,
List<AdditionalInfo> EmailAdditionalInfo);
public sealed record AdditionalInfo(string Key, string Value);
2 · Check your credits balance (free)
var balanceResponse = await client.GetFromJsonAsync<BalanceResponse>(
$"https://api.validemail.net/balance?token={ApiKey}");
Console.WriteLine($"Credits remaining: {balanceResponse!.Balance}");
public sealed record BalanceResponse(int Balance);
Uses the modern java.net.http.HttpClient (Java 11+) and org.json for parsing.
1 · Add a JSON dependency
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20240303</version>
</dependency>
2 · Verify an email address
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import org.json.JSONObject;
public class EmailVerifier {
private static final String API_URL = "https://api.validemail.net/";
private static final String API_KEY = "YOUR_API_KEY";
private static final HttpClient CLIENT = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
public static void main(String[] args) throws Exception {
JSONObject result = verifyEmail("someone@example.com", 3);
System.out.println("Valid: " + result.getBoolean("IsValid"));
System.out.println("Score: " + result.getInt("Score"));
System.out.println("State: " + result.getString("State"));
System.out.println("Reason: " + result.getString("Reason"));
if (result.getBoolean("IsValid") && result.getInt("Score") >= 80) {
System.out.println("Safe to send.");
}
}
static JSONObject verifyEmail(String email, int maxRetries) throws Exception {
JSONObject result = null;
for (int attempt = 0; attempt < maxRetries; attempt++) {
String url = API_URL + "?email=" + URLEncoder.encode(email, StandardCharsets.UTF_8)
+ "&token=" + API_KEY;
HttpRequest request = HttpRequest.newBuilder(URI.create(url))
.timeout(Duration.ofSeconds(90))
.GET()
.build();
HttpResponse<String> response = CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new RuntimeException("Request failed with HTTP " + response.statusCode() + ": " + response.body());
}
result = new JSONObject(response.body());
// "Unknown" means the verification is still in progress (e.g. greylisting).
int retryAfter = result.optInt("RetryAfterSeconds", 0);
if ("Unknown".equals(result.getString("State")) && retryAfter > 0) {
Thread.sleep(retryAfter * 1000L);
continue;
}
return result;
}
return result; // still pending after maxRetries — treat as risky
}
}
3 · Check your credits balance (free)
HttpRequest balanceRequest = HttpRequest.newBuilder(
URI.create("https://api.validemail.net/balance?token=" + API_KEY))
.GET()
.build();
HttpResponse<String> balanceResponse = CLIENT.send(balanceRequest, HttpResponse.BodyHandlers.ofString());
int balance = new JSONObject(balanceResponse.body()).getInt("balance");
System.out.println("Credits remaining: " + balance);
Standard library only — net/http and encoding/json (Go 1.18+).
1 · Verify an email address
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"time"
)
const (
apiURL = "https://api.validemail.net/"
apiKey = "YOUR_API_KEY"
)
type AdditionalInfo struct {
Key string `json:"Key"`
Value string `json:"Value"`
}
type VerificationResult struct {
IsValid bool `json:"IsValid"`
Score int `json:"Score"`
Email string `json:"Email"`
State string `json:"State"`
Reason string `json:"Reason"`
Domain string `json:"Domain"`
Free bool `json:"Free"`
Role bool `json:"Role"`
Disposable bool `json:"Disposable"`
AcceptAll bool `json:"AcceptAll"`
Tag bool `json:"Tag"`
MXRecord string `json:"MXRecord"`
RetryAfterSeconds *int `json:"RetryAfterSeconds"`
EmailAdditionalInfo []AdditionalInfo `json:"EmailAdditionalInfo"`
}
var client = &http.Client{Timeout: 90 * time.Second}
func verifyEmail(email string, maxRetries int) (*VerificationResult, error) {
var result VerificationResult
for attempt := 0; attempt < maxRetries; attempt++ {
query := url.Values{"email": {email}, "token": {apiKey}}
resp, err := client.Get(apiURL + "?" + query.Encode())
if err != nil {
return nil, err
}
body, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("request failed with HTTP %d: %s", resp.StatusCode, body)
}
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
// "Unknown" means the verification is still in progress (e.g. greylisting).
if result.State == "Unknown" && result.RetryAfterSeconds != nil {
time.Sleep(time.Duration(*result.RetryAfterSeconds) * time.Second)
continue
}
return &result, nil
}
return &result, nil // still pending after maxRetries — treat as risky
}
func main() {
result, err := verifyEmail("someone@example.com", 3)
if err != nil {
panic(err)
}
fmt.Println("Valid: ", result.IsValid)
fmt.Println("Score: ", result.Score)
fmt.Println("State: ", result.State)
fmt.Println("Reason:", result.Reason)
if result.IsValid && result.Score >= 80 {
fmt.Println("Safe to send.")
}
}
2 · Check your credits balance (free)
resp, err := client.Get("https://api.validemail.net/balance?token=" + apiKey)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var balance struct {
Balance int `json:"balance"`
}
if err := json.NewDecoder(resp.Body).Decode(&balance); err != nil {
panic(err)
}
fmt.Println("Credits remaining:", balance.Balance)
Standard library only — net/http and json (Ruby 3.0+).
1 · Verify an email address
require 'net/http'
require 'json'
API_URL = 'https://api.validemail.net/'
API_KEY = 'YOUR_API_KEY'
def verify_email(email, max_retries: 3)
result = nil
max_retries.times do
uri = URI(API_URL)
uri.query = URI.encode_www_form(email: email, token: API_KEY)
response = Net::HTTP.get_response(uri)
unless response.is_a?(Net::HTTPSuccess)
raise "Request failed with HTTP #{response.code}: #{response.body}"
end
result = JSON.parse(response.body)
# "Unknown" means the verification is still in progress (e.g. greylisting).
retry_after = result['RetryAfterSeconds']
if result['State'] == 'Unknown' && retry_after
sleep(retry_after)
next
end
return result
end
result # still pending after max_retries — treat as risky
end
result = verify_email('someone@example.com')
puts "Valid: #{result['IsValid']}"
puts "Score: #{result['Score']}"
puts "State: #{result['State']}"
puts "Reason: #{result['Reason']}"
puts 'Safe to send.' if result['IsValid'] && result['Score'] >= 80
2 · Check your credits balance (free)
uri = URI('https://api.validemail.net/balance')
uri.query = URI.encode_www_form(token: API_KEY)
balance = JSON.parse(Net::HTTP.get(uri))['balance']
puts "Credits remaining: #{balance}"
Keep your key secret. Run these samples on your backend only — never embed your API key in client-side code, public repositories, or mobile apps.
Credits Balance
Check your remaining verification credits — free to call, never consumes a credit.
https://api.validemail.net/balance?token=YOUR_API_KEY
Replace YOUR_API_KEY with your API key, or sign in to view your live balance URL.
Response
{
"balance": 12450
}
Response Guide
Use these fields to make reliable delivery decisions in your product workflow.
{
"IsValid": true,
"Score": 95,
"Email": "validemailnet@gmail.com",
"State": "Deliverable",
"Reason": "ACCEPTED EMAIL",
"Domain": "gmail.com",
"Free": true,
"Role": false,
"Disposable": false,
"AcceptAll": false,
"Tag": false,
"MXRecord": "gmail-smtp-in.l.google.com.",
"RetryAfterSeconds": null,
"EmailAdditionalInfo": []
}
| Field | Type | Description |
|---|---|---|
| IsValid | boolean | Overall validation status. |
| Score | integer (0-100) | Confidence score. Recommended threshold: 80+. |
| string | The exact queried email address. | |
| State | string | Deliverable, Not Deliverable, or Unknown (interim result — retry later). |
| Reason | string | Primary SMTP/validation reason (e.g. ACCEPTED EMAIL, REJECTED EMAIL, PENDING, GREYLISTED). |
| Domain | string | Extracted domain from the email. |
| Free | boolean | True when provider is free (e.g., Gmail). |
| Role | boolean | True for role inboxes (info, support, admin). |
| Disposable | boolean | True for temporary/disposable addresses. |
| AcceptAll | boolean | True when domain accepts all recipients. |
| Tag | boolean | True for tagged aliases (user+tag@domain). |
| MXRecord | string | Resolved mail exchange server. |
| RetryAfterSeconds | integer / null | Set only on Unknown interim results: seconds to wait before re-querying for the final verdict. |
| EmailAdditionalInfo | array | Reserved metadata collection. |