PHP Form URL/E-mail

sa sahaya jerish Updated 17 Oct 2026
5 min read ·Lesson 93 of 109
In this post

Email addresses and website URLs are among the most common form inputs — and among the easiest to validate incorrectly. Hand-written regular expressions for them are usually either too strict (rejecti

Email addresses and website URLs are among the most common form inputs — and among the easiest to validate incorrectly. Hand-written regular expressions for them are usually either too strict (rejecting valid addresses) or too loose (accepting dangerous input). PHP's filter extension provides tested validators, and this lesson shows how to use them correctly, including their limitations.


Validating Email Addresses

FILTER_VALIDATE_EMAIL

<?php
$emails = [
    'asha@example.com',
    'Asha.K+news@Example.COM',
    'asha@localhost',
    'asha@@example.com',
    'asha@example',
    '.asha@example.com',
    'asha @example.com',
];

foreach ($emails as $email) {
    $result = filter_var($email, FILTER_VALIDATE_EMAIL) !== false ? 'valid' : 'invalid';
    echo str_pad($email, 26) . $result . "\n";
}

Output

asha@example.com          valid
Asha.K+news@Example.COM   valid
asha@localhost            invalid
asha@@example.com         invalid
asha@example              invalid
.asha@example.com         invalid
asha @example.com         invalid

What the Filter Checks

  • There is exactly one @ separating a local part and a domain.
  • The local part uses allowed characters — including ., +, and _ — and does not start or end with a dot.
  • The domain consists of valid labels separated by dots; a domain without a dot (localhost, example) is rejected.
  • No spaces are allowed.

On success, filter_var() returns the email string; on failure, false.

What the Filter Does Not Check

  • Whether the domain exists or accepts mail.
  • Whether the mailbox exists.
  • Whether the user actually owns the address.

The only reliable way to confirm an email address is to send a verification email containing a unique link or code. Format validation simply catches typos early.

International Email Addresses

<?php
$email = 'ஆஷா@example.com';

var_dump(filter_var($email, FILTER_VALIDATE_EMAIL));
var_dump(filter_var($email, FILTER_VALIDATE_EMAIL, FILTER_FLAG_EMAIL_UNICODE));

Output

bool(false)
string(21) "ஆஷா@example.com"

By default, only ASCII characters are allowed in the local part. FILTER_FLAG_EMAIL_UNICODE (PHP 7.1+) accepts Unicode local parts. (var_dump() reports the length in bytes: each Tamil character here takes 3 bytes in UTF-8.) International domain names (such as Tamil or Hindi domains) must first be converted to their ASCII form with idn_to_ascii() from the intl extension. Before accepting Unicode addresses, check that your mail server and email provider support them.

Normalizing Email Addresses

<?php
function normalizeEmail(string $input): ?string
{
    $email = trim($input);

    if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
        return null;
    }

    $at = strrpos($email, '@');

    return substr($email, 0, $at) . '@' . strtolower(substr($email, $at + 1));
}

var_dump(normalizeEmail('  Asha.K+news@Example.COM '));
var_dump(normalizeEmail('asha@example'));

Output

string(23) "Asha.K+news@example.com"
NULL
  • Surrounding spaces (common when copying and pasting) are removed before validation.
  • The domain is lowercased because domain names are case-insensitive.
  • The local part is kept as typed: technically it may be case-sensitive, although most providers ignore case. When checking for duplicate accounts, many applications compare emails case-insensitively (for example, with a case-insensitive database collation).

Validating URLs

FILTER_VALIDATE_URL

<?php
$urls = [
    'https://gocourse.in/php/arrays',
    'http://localhost:8000/test',
    'gocourse.in',
    'https://exa mple.com',
    'ftp://files.example.com/report.pdf',
];

foreach ($urls as $url) {
    $result = filter_var($url, FILTER_VALIDATE_URL) !== false ? 'valid' : 'invalid';
    echo str_pad($url, 36) . $result . "\n";
}

Output

https://gocourse.in/php/arrays      valid
http://localhost:8000/test          valid
gocourse.in                         invalid
https://exa mple.com                invalid
ftp://files.example.com/report.pdf  valid
  • A URL must have a scheme (https://); gocourse.in alone is rejected, even though users often type it this way.
  • Spaces and other invalid characters are rejected.
  • Any scheme is accepted — not only http and https.

Optional Flags

FlagRequires
FILTER_FLAG_PATH_REQUIREDA path after the host (https://example.com/page)
FILTER_FLAG_QUERY_REQUIREDA query string (?key=value)

The Scheme Problem: Dangerous URLs

Because FILTER_VALIDATE_URL accepts any scheme, it also accepts URLs that are dangerous when used as links, such as javascript: URLs crafted to include a host (for example, javascript://example.com/%0Aalert(1)). If such a "website" from a user profile is printed into <a href="...">, clicking it runs JavaScript in your site's context — an XSS attack.

Always restrict the scheme for URLs that will become links:

<?php
function validateWebUrl(string $input): ?string
{
    $url = trim($input);

    if (filter_var($url, FILTER_VALIDATE_URL) === false) {
        return null;
    }

    $scheme = strtolower((string) parse_url($url, PHP_URL_SCHEME));

    return in_array($scheme, ['http', 'https'], true) ? $url : null;
}

$tests = [
    ' https://gocourse.in/php ',
    'gocourse.in',
    'javascript://example.com/%0Aalert(1)',
    'ftp://files.example.com/report.pdf',
];

foreach ($tests as $input) {
    $result = validateWebUrl($input);
    echo str_pad(trim($input), 38) . ($result === null ? 'rejected' : 'accepted') . "\n";
}

Output

https://gocourse.in/php               accepted
gocourse.in                           rejected
javascript://example.com/%0Aalert(1)  rejected
ftp://files.example.com/report.pdf    rejected

How It Works

  1. The input is trimmed, then validated as a URL.
  2. parse_url(..., PHP_URL_SCHEME) extracts the scheme, which is compared with an allow-list.
  3. Only http and https URLs are accepted, which blocks javascript:, data:, file:, and other schemes.

Being Helpful With Missing Schemes

Users often type gocourse.in without https://. A friendly form can add the scheme before validating:

<?php
function withDefaultScheme(string $input): string
{
    $url = trim($input);

    return preg_match('#^[a-z][a-z0-9+.-]*://#i', $url) === 1 ? $url : 'https://' . $url;
}

echo withDefaultScheme('gocourse.in/php') . "\n";
echo withDefaultScheme('http://example.com') . "\n";

Output

https://gocourse.in/php
http://example.com

The result must still pass validateWebUrl() afterwards.


Even after validation, escape URLs when printing them, and mark external links appropriately:

<?php
$website = 'https://example.com/profile?name=asha&ref=gocourse';
?>
<a href="<?= htmlspecialchars($website) ?>" rel="nofollow ugc noopener" target="_blank">
    <?= htmlspecialchars(parse_url($website, PHP_URL_HOST)) ?>
</a>

Output (HTML)

<a href="https://example.com/profile?name=asha&ref=gocourse" rel="nofollow ugc noopener" target="_blank">
    example.com
</a>
  • htmlspecialchars() escapes & as & (correct in HTML attributes) and neutralizes quotes that could break out of the attribute.
  • rel="nofollow ugc" tells search engines that the link is user-generated and not endorsed.
  • noopener prevents the opened page from controlling your page through window.opener.

Security note: If your server ever fetches a URL supplied by a user (for previews or imports), validating the format is not enough. An attacker could point it at internal addresses (http://127.0.0.1/admin, cloud metadata services). This is called Server-Side Request Forgery (SSRF); such features need additional checks on the resolved IP address.


Common Mistakes

Writing Your Own Email Regex

Effect: Valid addresses (with + or long domains) are rejected, or invalid ones accepted.

Fix: Use FILTER_VALIDATE_EMAIL, then verify ownership by email.

Validating Before Trimming

Effect: Pasted values with spaces are rejected.

Fix: trim() first, then validate.

Effect: javascript: links lead to XSS.

Fix: Allow only http and https.

Printing URLs Without Escaping

Effect: Quotes in a URL can break out of the href attribute.

Fix: htmlspecialchars() in attributes.

Treating a Valid Format as Proof

Effect: Fake or mistyped (but well-formed) addresses are trusted.

Fix: Send verification emails; check link targets if they matter.


Best Practices

  • Trim input, then validate with FILTER_VALIDATE_EMAIL or FILTER_VALIDATE_URL.
  • Normalize email domains to lowercase and verify addresses with a confirmation email.
  • Restrict URL schemes to http and https for user-supplied links.
  • Escape URLs on output and add rel attributes for external, user-generated links.
  • Treat server-side fetching of user URLs as a separate security problem (SSRF).

Official reference: https://www.php.net/manual/en/filter.filters.validate.php

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Home PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement PHP Home PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope PHP Casting Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence Continue Statement Modify Strings PHP If...Else...Elseif PHP If Modify Strings PHP If Operators PHP Functions Concatenate Strings PHP If...Else Slicing Strings User-defined Functions Slicing Strings PHP Shorthand if Escape Characters Default Argument Values PHP Nested if Pass by Reference String Interpolation Named Arguments PHP File Upload Variadic Functions Return Values Search in Strings Multibyte Strings Type Declarations in Functions PHP Numbers PHP Math PHP Floats PHP Random Numbers PHP Constants PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Cookies PHP Destructor PHP Access Modifiers Readonly Properties PHP Sessions PHP Inheritance Method Overriding PHP Filters The final Keyword CSRF Protection PHP Filters Advanced Session Security Secure Cookies PHP Magic Constants File Upload Security PHP Callback Functions PHP Operators Filesystem Security PHP JSON Arithmetic Operators Error Reporting in Production Hiding PHP Assignment Operators PHP Configuration (php.ini) Comparison Operators PHP Command Line (CLI) PHP Exceptions Increment / Decrement Operators Migrating to PHP 8 PHP Form Validation PHP Form Required PHP Form URL/E-mail Error Handling Form Input Sanitizing Escaping Output (htmlspecialchars) Custom Error Handler Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators
Ask about this post
AI Ask about this post

Ask questions about PHP Form URL/E-mail and get answers drawn from it.

Signed-in readers only.