Skip to content

How to Extract a Domain Name from an Email Address in Python

Learn Python methods to extract domain names from email addresses, including simple split() techniques, regex patterns, batch processing, and handling edge cases like invalid formats or multiple @ symbols.

Extracting the domain name from an email address - the part after the @ symbol - is a common task in data cleaning, user analytics, email validation, and spam filtering. For example, from "user@example.com", you need to extract "example.com".

In this guide, you will learn multiple methods to extract domain names from email addresses in Python, from simple string operations to regex-based approaches, along with handling edge cases and batch processing.

The simplest and most readable approach uses Python's built-in split() method to divide the email string at the @ symbol:

email = "user@example.com"

domain = email.split("@")[1]

print(domain)

Output:

example.com

How it works:

  1. split("@") divides the string into a list: ["user", "example.com"].
  2. Index [1] retrieves the second element - the domain name.

Extracting Both Username and Domain

email = "john.doe@company.org"

username, domain = email.split("@")

print(f"Username: {username}")
print(f"Domain: {domain}")

Output:

Username: john.doe
Domain: company.org

Using partition()

The partition() method splits a string into exactly three parts: the portion before the separator, the separator itself, and the portion after it:

email = "user@example.com"

before, sep, domain = email.partition("@")

print(domain)

Output:

example.com

This method is useful when you want a clean unpacking without worrying about multiple @ symbols - partition() always splits on the first occurrence.

Using Regular Expressions

For complex validation or pattern matching scenarios, regular expressions provide precise control:

import re

email = "user@example.com"

match = re.search(r"@([a-zA-Z0-9.-]+)", email)

if match:
    domain = match.group(1)
    print(domain)

Output:

example.com

How it works:

  1. The pattern @([a-zA-Z0-9.-]+) matches the @ symbol followed by one or more valid domain characters.
  2. match.group(1) returns the captured group - the domain name without the @.

Extracting Subdomain, Domain, and TLD

Regex allows you to extract individual parts of the domain:

import re

email = "user@mail.example.co.uk"

match = re.search(r"@(.+)$", email)

if match:
    full_domain = match.group(1)
    parts = full_domain.split(".")

    tld = ".".join(parts[-2:]) if len(parts) > 2 else parts[-1]
    print(f"Full domain: {full_domain}")
    print(f"Parts: {parts}")

Output:

Full domain: mail.example.co.uk
Parts: ['mail', 'example', 'co', 'uk']

Batch Processing: Extract Domains from Multiple Emails

In real-world applications, you often need to process a list of email addresses:

emails = [
    "alice@gmail.com",
    "bob@company.org",
    "carol@university.edu",
    "dave@startup.io",
    "eve@gmail.com",
]

domains = [email.split("@")[1] for email in emails]
print("All domains:", domains)

unique_domains = set(domains)
print("Unique domains:", unique_domains)

from collections import Counter

domain_counts = Counter(domains)
print("Domain counts:", dict(domain_counts))

Output:

All domains: ['gmail.com', 'company.org', 'university.edu', 'startup.io', 'gmail.com']
Unique domains: {'startup.io', 'gmail.com', 'company.org', 'university.edu'}
Domain counts: {'gmail.com': 2, 'company.org': 1, 'university.edu': 1, 'startup.io': 1}

Handling Edge Cases

Emails with No @ Symbol

If the input might not be a valid email address, split("@") can produce unexpected results:

Problem:

invalid = "not-an-email"

domain = invalid.split("@")[1]  # IndexError: list index out of range

Fix - validate before extracting:

def extract_domain(email):
    """Safely extract domain from an email address."""
    if "@" not in email:
        return None
    parts = email.split("@")
    if len(parts) != 2 or not parts[1]:
        return None
    return parts[1]

print(extract_domain("user@example.com"))    # example.com
print(extract_domain("not-an-email"))        # None
print(extract_domain("user@"))               # None
print(extract_domain("@example.com"))        # example.com
print(extract_domain("a@b@c.com"))           # None (because of multiple @ symbols)

Output:

example.com
None
None
example.com
None

Emails with Multiple @ Symbols

Technically, email addresses can contain multiple @ symbols if the local part is quoted (e.g., "user@name"@example.com). For strict parsing:

email = '"user@name"@example.com'

domain = email.rsplit("@", 1)[1]

print(domain)

Output:

example.com

Stripping Whitespace and Normalizing Case

Real-world data often contains leading/trailing whitespace and inconsistent casing:

emails = ["  User@Example.COM  ", "admin@COMPANY.org ", " test@Test.IO"]

cleaned_domains = [
    email.strip().split("@")[1].lower()
    for email in emails
]

print(cleaned_domains)

Output:

['example.com', 'company.org', 'test.io']

Extracting Domains from a Pandas DataFrame

When working with email data in a DataFrame:

import pandas as pd

df = pd.DataFrame({
    "name": ["Alice", "Bob", "Carol"],
    "email": ["alice@gmail.com", "bob@company.org", "carol@university.edu"],
})

df["domain"] = df["email"].str.split("@").str[1]

print(df)

Output:

    name                 email          domain
0  Alice       alice@gmail.com       gmail.com
1    Bob       bob@company.org     company.org
2  Carol  carol@university.edu  university.edu

Comparison of Methods

Method Readability Handles Edge Cases Validation Best For
split("@")[1] ✅ Highest ❌ Needs guard ❌ No Simple, trusted input
rsplit("@", 1)[1] ✅ High ✅ Multiple @ ❌ No Robust extraction
partition("@")[2] ✅ High ✅ First @ only ❌ No Clean unpacking
re.search() ⚠️ Moderate ✅ Yes ✅ Yes Validation + extraction

Summary

Extracting domain names from email addresses in Python is straightforward with the right approach:

  • Use split("@")[1] for the simplest and fastest extraction - ideal for clean, validated data.
  • Use rsplit("@", 1)[1] for a more robust version that handles edge cases with multiple @ symbols.
  • Use partition("@")[2] for clean three-way unpacking of the email components.
  • Use regular expressions when you need simultaneous validation and extraction, or need to parse complex domain structures.
  • Always validate input before extraction to handle missing @ symbols, empty strings, or malformed addresses.
  • Use .strip().lower() to normalize whitespace and casing in real-world data.
Navigation