mrkeyoor.com_
Sat 08 Aug 17:38 UTC
PyPIUtilsupdated 08 Aug 2026

validators

validators is a collection of small Python functions for checking one value at a time without defining a form or schema. It covers email addresses, URLs, domains, IP addresses, UUIDs, hashes, payment-card formats, country and currency codes, cron strings, slugs, lengths, numeric ranges, and more. A successful check returns True; a failed check returns a false-valued ValidationError object that records the function and arguments, or can be configured to raise.

Verdict

A good grab bag for small, explicit format checks, especially when a schema library would be ceremony. Do not confuse syntactic acceptance with real-world validity, and normalize its unusual True-or-ValidationError result at your application boundary.

API stability4/5The top-level function style and True-or-ValidationError contract are consistent across the package, and version 0.35.0 still exposes the long-standing email, url, domain, IP, UUID, length, and related names. The package remains below 1.0 and is classified Beta, while acceptance rules and keyword options can evolve as RFC interpretations and datasets change.
Docs3/5The generated reference documents each validator's arguments, examples, return type, and many RFC-related options, and the source docstrings are detailed. Discovery is less polished: the repository README is very short, points to a documentation site under a different GitHub owner, and notes that the original documentation will be restored after versioning work is ready.
Maintenance4/5PyPI serves version 0.35.0, the repository was pushed in March 2026, and it is not archived. There are 32 open issues and pull requests, and project metadata links a changelog, security policy, linting, static analysis, and documentation workflows. The Beta classifier and split documentation ownership keep this below the top score.
Ecosystem4/5The supplied weekly download measurement is 7,399,074 and the repository has 1,121 stars, showing broad use for a focused utility. Its validators cover many common internet, finance, country, encoding, and identifier formats, but it is intentionally not a model-validation ecosystem and offers only one declared optional dependency group for Ethereum checks.

Use it if

  • You need a readable one-line check for common string and identifier formats without bringing in a schema system
  • You want failure objects that retain which validator and arguments failed while still working in boolean conditions
  • You need configurable URL, hostname, domain, or IP checks, including private-address and TLD restrictions
  • You are writing a few boundary checks in an existing Python application that already owns normalization and error messages
Skip it if

Setup reality

`pip install validators` is enough for the main validators. Version 0.35.0 requires Python 3.9 or newer and has no mandatory runtime dependency; Ethereum address validation is the exception and is exposed through the `crypto-eth-addresses` extra, which installs `eth-hash[pycryptodome]`. The first surprise is the result type. Valid input returns the literal True, while invalid input returns a `ValidationError` instance whose `__bool__` method is False. `if validators.email(value)` works, but `validators.email(value) is False` does not, and returning the result directly from a JSON API will expose a non-serializable object. Keep the result when you need its `func`, arguments, or reason. Pass `r_ve=True` to any decorated validator to raise on failure, or set `RAISE_VALIDATION_ERROR=True` to change behavior process-wide; the environment switch is convenient but can silently alter third-party code in the same process. These are format checks, not normalizers. Trim input, decide Unicode policy, and store canonical forms yourself. URL and host validation needs explicit product choices about ports, local hosts, private IP addresses, valid TLDs, strict query parsing, and trailing dots. Email validation does not verify DNS or delivery. Card checks do not make handling card data compliant. Finally, Python 3.9 is accepted by the package even though the README calls out that version's end of life, so your application runtime policy may need to be stricter than the package metadata.

Patterns

Check an email addressvalidate-email

import validators

result = validators.email('someone@example.com')
if result:
    accept_address()
else:
    reject_address(str(result))

This checks format only. A false result is a ValidationError object, not the literal False, and no DNS or mailbox check occurs.

Raise a validation exceptionraise-on-invalid

import validators
from validators import ValidationError

try:
    validators.email('bogus@@', r_ve=True)
except ValidationError as error:
    print(error.func.__name__, error.value)

The r_ve keyword is consumed by the decorator and works for every validator wrapped by the package.

Require an HTTP or HTTPS URLvalidate-url

import validators

def http_scheme(scheme: str) -> bool:
    return scheme in {'http', 'https'}

valid = validators.url(
    'https://example.com/docs?q=python',
    validate_scheme=http_scheme,
)

The default scheme validator accepts more than web URLs; pass product policy explicitly when only HTTP and HTTPS belong.

Reject URLs containing private IP addressesreject-private-url

import validators

result = validators.url(
    'http://192.168.1.10/admin',
    private=False,
)
assert not result

This option applies to embedded IP literals, not DNS resolution. It is not by itself an SSRF defense because a hostname can resolve to a private address later.

Require a domain with a recognized TLDvalidate-domain

import validators

result = validators.domain('example.com', consider_tld=True)
assert result is True

consider_tld checks the package's IANA-derived list; leave it off for internal suffixes and test domains that are valid only in your network.

Require a private IPv4 addressvalidate-private-ipv4

import validators

assert validators.ipv4('10.2.3.4', private=True) is True
assert not validators.ipv4('8.8.8.8', private=True)

The private option includes local, loopback, and broadcast categories documented by the implementation, so confirm that grouping matches your security rule.

Check a UUID valuevalidate-uuid

from uuid import UUID
import validators

assert validators.uuid('2bc1c94f-0deb-43e9-92a1-4775189ec9f8') is True
assert validators.uuid(UUID('2bc1c94f-0deb-43e9-92a1-4775189ec9f8')) is True

The validator accepts UUID objects and UUID-shaped strings; its docstring calls this UUID v4, but the implementation constructs UUID without enforcing a version field.

Check a lowercase URL slugvalidate-slug

import validators

assert validators.slug('release-notes-2026') is True
assert not validators.slug('Release Notes')

The accepted grammar is lowercase ASCII letters and digits separated by single hyphens; it does not create or normalize a slug.

Constrain string lengthvalidate-length

import validators

result = validators.length('display name', min_val=3, max_val=40)
assert result is True

Length uses Python len, so it counts Unicode code points rather than bytes or user-perceived grapheme clusters.

Check a comparable value rangevalidate-range

from datetime import datetime, timezone
import validators

result = validators.between(
    datetime.now(timezone.utc),
    min_val=datetime(2026, 1, 1, tzinfo=timezone.utc),
)

Both bounds are inclusive. Mixing incomparable types or naive and aware datetimes produces a captured ValidationError unless raising mode is enabled.

Check a five-field cron expressionvalidate-cron

import validators

assert validators.cron('0 2 * * 1-5') is True
assert not validators.cron('30-20 * * * *')

Format validity does not guarantee that a specific scheduler supports every token or interprets weekdays and time zones the same way.

Create a validator with the same result contractdefine-custom-validator

from validators import validator

@validator
def even(value: int):
    return value % 2 == 0

assert even(4) is True
failure = even(5)
assert not failure

The decorator converts false results and common value, type, or Unicode errors into false-valued ValidationError objects.

Alternatives

PackageRegistryPick it when
pydanticPyPIYou need typed models, coercion, nested schemas, reusable field rules, and structured error locations
email-validatorPyPIEmail addresses are the main concern and you need normalization plus optional DNS deliverability checks
rfc3986PyPIYou need URI parsing and RFC-focused validation with components you can normalize and inspect