PHP email verification
Verify emails in PHP with Verifly
Add live email verification to any PHP app with cURL or Guzzle. Verifly is an API-first, pay-as-you-go service that returns a clean JSON verdict you can decode and branch on inside Laravel, Symfony, WordPress, or plain PHP.
$ch = curl_init(
'https://verifly.email/api/v1/verify?email=' . urlencode('user@example.com')
);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer vf_YOUR_KEY',
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
echo $data['result'] . ' ' . ($data['is_valid'] ? 'valid' : 'invalid');Real-time SMTP mailbox checks
Single, batch, and async bulk verification
Disposable, role account, and catch-all detection
Pay-as-you-go credits with no subscription lock-in
Search fit
Built for PHP email verification
Use Verifly when you need a simple API, predictable pricing, and clean JSON results before emails hit your product, CRM, or campaign tool.
Email verification in PHP applications
PHP still powers a huge share of the web — Laravel and Symfony apps, WordPress and its plugin ecosystem, and countless bespoke scripts behind contact forms. Every one of them collects email addresses, and every one of them faces the same trap: PHP's filter_var with FILTER_VALIDATE_EMAIL only confirms the string is well-formed. It cannot tell you the mailbox exists, that the domain is a disposable throwaway, or that the address is a generic role inbox that will never engage.
Verifly answers that with a single HTTP request. You have two natural clients in PHP: the ext-curl functions that ship with virtually every install, or the Guzzle library that Laravel and Symfony already pull in. Either way you send an address with a Bearer header, Verifly runs a live SMTP mailbox probe, and json_decode gives you an associative array with a result of deliverable, undeliverable, or risky plus flags for disposable, role, catch-all, and smtp. That drops straight into an if or match expression.
Because Verifly is pay-as-you-go — $2 per 1,000 checks down to $0.60 per 1,000 at volume — it works for a low-traffic WordPress contact form and a high-volume SaaS signup alike, with no monthly plan to commit to. Self-register for 100 free credits with no card and no captcha, store the vf_ key in your .env, and reuse it everywhere.
Batch-verify emails with Guzzle
For a list of addresses, send them together to /verify/batch instead of firing one request per row. Post a JSON body with an emails array and read back a results array in order. Guzzle makes this concise, and json_decode turns the response into arrays you can filter with array_filter.
use GuzzleHttp\Client;
$client = new Client();
$emails = ['ada@example.com', 'info@some-domain.com', 'noreply@disposable.tld'];
$response = $client->post('https://verifly.email/api/v1/verify/batch', [
'headers' => ['Authorization' => 'Bearer vf_YOUR_KEY'],
'json' => ['emails' => $emails],
]);
$results = json_decode((string) $response->getBody(), true)['results'];
$clean = array_filter($results, fn($r) => $r['result'] === 'deliverable');
printf("Keeping %d of %d\n", count($clean), count($results));
foreach ($results as $r) {
if (!empty($r['disposable']) || !empty($r['role'])) {
echo 'drop: ' . $r['email'] . ' (' . $r['result'] . ')' . PHP_EOL;
}
}Validate at signup in Laravel
The highest-leverage place to verify in a PHP app is the registration request. A custom validation rule or a quick check in your controller — with a short cURL timeout so a slow probe never hangs the request, and fail-open behaviour on error so signups are never blocked by an outage — lets you reject disposable addresses and warn on undeliverable ones before the user row is written.
function emailOk(string $email): bool {
$ch = curl_init(
'https://verifly.email/api/v1/verify?email=' . urlencode($email)
);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 8,
CURLOPT_HTTPHEADER => ['Authorization: Bearer vf_YOUR_KEY'],
]);
$body = curl_exec($ch);
curl_close($ch);
if ($body === false) {
return true; // fail open on network error
}
$data = json_decode($body, true);
if (!empty($data['disposable'])) {
return false;
}
return ($data['result'] ?? '') !== 'undeliverable';
}FAQ
Frequently asked questions
Should I use cURL or Guzzle with Verifly?
Either works. ext-curl ships with almost every PHP install and needs no dependency, while Guzzle is cleaner and is already present in Laravel and Symfony projects. Both send a GET to /api/v1/verify with a Bearer header and decode JSON.
Isn't PHP's filter_var enough to validate an email?
filter_var with FILTER_VALIDATE_EMAIL only checks syntax. It passes addresses whose mailbox was deleted, whose domain is disposable, or that are role inboxes. Verifly adds the live SMTP check that filter_var cannot do.
How do I verify a whole list of emails?
Send them to POST /api/v1/verify/batch as a JSON emails array rather than looping the single endpoint. You get a results array back in order, which you can json_decode and array_filter down to deliverable rows.
How do I keep verification from hanging a request?
Set CURLOPT_TIMEOUT (or a Guzzle timeout) to a few seconds and fail open when the call errors. That caps the added latency and ensures a slow probe never blocks a signup.
What is in the decoded response?
json_decode gives an array with result (deliverable, undeliverable, or risky), is_valid, and boolean flags disposable, role, catch_all, and smtp. Branch on result and use the flags to strip throwaway or role addresses.
What does PHP email verification cost?
Pay-as-you-go from $2 per 1,000 checks down to $0.60 per 1,000 at volume, with 100 free credits on self-register. No subscription, so a small WordPress form and a busy SaaS pay only for what they check.