ZetCode

Python Faker

last modified October 30, 2026 Python 3.15

In this article we show how to generate fake data in Python with the Faker package.

Faker

Faker is a Python library that generates fake data. Fake data is often used for testing or for filling databases with dummy data. Faker is inspired by PHP's Faker, Perl's Data::Faker, and Ruby's Faker.

The package is installed with pip.

$ pip install Faker

Faker generator

The faker.Faker class creates and initializes a faker generator, which generates data through methods named after the type of data, such as name or address.

Faker delegates the data generation to providers. The default locale is en_US. Faker supports many other locales; they differ in level of completion.

The data is random, so the output of the examples differs on each run. Seeding the generator, shown later, makes it reproducible.

Simple Faker

The following example is a simple demonstration of Faker.

simple.py
from faker import Faker

faker = Faker()

print(f'name: {faker.name()}')
print(f'address: {faker.address()}')

print(f'text: {faker.text()}')

The example outputs a fake name, address, and text. The address and the text span several lines.

$ python simple.py
name: Stephanie Mayer
address: 7441 Jones Shoal
West Jasmine, ND 93968
text: Into seek laugh important tough hold. Cost foreign central trouble general.
Treatment key tough accept space top but. Least special tax PM. Science year fill decision factor.

Faking names

In the second example, we fake data related to user names.

names.py
from faker import Faker

faker = Faker()

print(f'Name: {faker.name()}')
print(f'First name: {faker.first_name()}')
print(f'Last name: {faker.last_name()}')

print('--------------------------')

print(f'Male name: {faker.name_male()}')
print(f'Female name: {faker.name_female()}')
print(f'Prefix: {faker.prefix()}, suffix: {faker.suffix()}')

The example creates fake full names, first names, and last names, names of males and females, and name prefixes and suffixes.

$ python names.py
Name: Victoria Chen
First name: Ariel
Last name: Blackwell
--------------------------
Male name: Matthew Camacho
Female name: Melissa Velasquez
Prefix: Mx., suffix: Jr.

Faking jobs

Jobs are generated with job.

jobs.py
from faker import Faker

faker = Faker()

for _ in range(6):
    print(faker.job())

The example creates six fake jobs.

$ python jobs.py
Surveyor, building control
Estate manager/land agent
Volunteer coordinator
Exhibitions officer, museum/gallery
Nurse, adult
Lobbyist

Faking locale data

Faker supports localized data. The locale is passed to the constructor.

localized.py
from faker import Faker

faker = Faker('cs_CZ')

for _ in range(3):
    name = faker.name()
    address = faker.address().replace('\n', ', ')
    phone = faker.phone_number()

    print(f'{name}; {address}; {phone}')

The example generates fake Czech names, addresses, and phone numbers. The locale code is cs_CZ: the language code followed by the country code. We replace the newline in the address with a comma to keep each person on one line.

$ python localized.py
Aleš Doležal CSc.; Opletalova 17, 242 17 Rtyně v Podkrkonoší; +420 605 417 169
Marie Ježková; K Lučinám 987, 304 61 Město Touškov; 00420 608 966 236
Vendula Králová; Chotětovská 474, 503 88 Chotěboř; +420 602 577 976

Multiple locales

The constructor also accepts a list of locales.

multi_locale.py
from faker import Faker

faker = Faker(['sk_SK', 'de_DE', 'ja_JP'])

for _ in range(4):
    print(faker.name())

print('--------------------------')

for locale in faker.locales:
    print(f'{locale}: {faker[locale].city()}')

Each call picks one of the locales at random. To use a specific locale, we index the generator with the locale name. The locales attribute lists the configured locales.

$ python multi_locale.py
Martina Schmidtke-Thies
Sibille Vollbrecht B.Sc.
小林 さゆり
Jürgen Mielcarek-Bauer
--------------------------
sk_SK: Padáň
de_DE: Feuchtwangen
ja_JP: 横浜市港南区

Faking currencies

The following example creates fake data for currencies.

currencies.py
from faker import Faker

faker = Faker()

print(f'currency: {faker.currency()}')
print(f'currency name: {faker.currency_name()}')
print(f'currency code: {faker.currency_code()}')
print(f'price tag: {faker.pricetag()}')

The currency method returns a tuple of the code and the name. The pricetag method returns a formatted price.

$ python currencies.py
currency: ('AFN', 'Afghan afghani')
currency name: Namibian dollar
currency code: BDT
price tag: $35,255.57

Faking words and text

Faker can create dummy words, sentences, and paragraphs.

words.py
from faker import Faker

faker = Faker()

print(f'a word: {faker.word()}')
print(f'six words: {faker.words(6)}')

words = ['forest', 'blue', 'cloud', 'sky', 'wood', 'falcon']

print(f'customized unique words: {faker.words(3, words, True)}')

print(f'sentence: {faker.sentence(nb_words=5)}')
print(f'paragraph: {faker.paragraph(nb_sentences=2)}')

The example creates dummy words and text.

words = ['forest', 'blue', 'cloud', 'sky', 'wood', 'falcon']

print(f'customized unique words: {faker.words(3, words, True)}')

We can also pick words from our own list; the third argument requests unique words.

print(f'sentence: {faker.sentence(nb_words=5)}')

By default, the number of words in a sentence varies by up to 40 percent around nb_words; with variable_nb_words=False, the number is exact.

$ python words.py
a word: run
six words: ['still', 'lot', 'or', 'paper', 'marriage', 'own']
customized unique words: ['sky', 'sky', 'cloud']
sentence: Expect scientist half.
paragraph: Whole far try decision along else. Should language minute way.

Faking profiles

Faker can create simple dummy profiles with simple_profile and extended profiles with profile.

profiles.py
from pprint import pprint

from faker import Faker

faker = Faker()

profile1 = faker.simple_profile()
pprint(profile1)

print('--------------------------')

profile2 = faker.simple_profile(sex='M')
pprint(profile2)

print('--------------------------')

profile3 = faker.profile(fields=['name', 'job', 'company', 'blood_group',
                                 'website'], sex='F')
pprint(profile3)

The example creates dummy profiles of females and males and prints them with pprint. The fields parameter of profile limits the profile to the selected fields.

$ python profiles.py
{'address': '31981 Tom Roads\nPort Kathleen, TX 84438',
 'birthdate': datetime.date(1990, 5, 17),
 'mail': 'scook@gmail.com',
 'name': 'Deanna Byrd',
 'sex': 'F',
 'username': 'davidjohnson'}
--------------------------
{'address': 'Unit 0571 Box 5796\nDPO AA 72660',
 'birthdate': datetime.date(1942, 5, 22),
 'mail': 'mbond@yahoo.com',
 'name': 'David Estrada',
 'sex': 'M',
 'username': 'nathanliu'}
--------------------------
{'blood_group': 'A-',
 'company': 'Reyes and Sons',
 'job': 'Chartered certified accountant',
 'name': 'Cynthia Davis',
 'website': ['http://orr-harrington.com/']}

Faking numbers

Faker can generate random digits, integers, floats, decimals, booleans, and elements of a collection.

fake_numbers.py
from faker import Faker

faker = Faker()

print(f'Random int: {faker.random_int()}')
print(f'Random int: {faker.random_int(0, 100)}')
print(f'Random int with step: {faker.random_int(0, 100, step=10)}')
print(f'Random digit: {faker.random_digit()}')
print(f'Float: {faker.pyfloat(left_digits=2, right_digits=3, positive=True)}')
print(f'Decimal: {faker.pydecimal(left_digits=4, right_digits=2, positive=True)}')
print(f'Boolean: {faker.pybool()}')
print(f'Element: {faker.random_element(["red", "green", "blue"])}')
print(f'Elements: {faker.random_elements("abcdefgh", length=3, unique=True)}')

We can specify the bounds and the step in the random_int method. The pyfloat and pydecimal methods take the number of digits before and after the decimal point. The random_elements method picks several elements; with unique=True, without repetition.

$ python fake_numbers.py
Random int: 1065
Random int: 2
Random int with step: 30
Random digit: 7
Float: 18.886
Decimal: 6560.95
Boolean: True
Element: blue
Elements: ['e', 'g', 'a']

Formatting templates

Faker can fill placeholders in a template string.

formats.py
from faker import Faker

faker = Faker()

print(faker.numerify('order-####'))
print(faker.lexify('????-id'))
print(faker.bothify('##-??-##', letters='ABCDEF'))
print(faker.hexify('^^:^^:^^'))
print(faker.pystr_format('{{first_name}} ({{random_int}})'))

The numerify method replaces # with digits, lexify replaces ? with letters, and bothify does both; its letters parameter sets the letters to choose from. The hexify method replaces ^ with hexadecimal digits. The pystr_format method calls the methods named in double curly brackets.

$ python formats.py
order-0801
ayBo-id
69-DA-04
c6:40:f0
Tina (5375)

Faking hashes and UUIDs

Faker can generate dummy hashes and UUIDs.

hash_uuid.py
from faker import Faker

faker = Faker()

print(f'md5: {faker.md5()}')
print(f'sha1: {faker.sha1()}')
print(f'sha256: {faker.sha256()}')
print(f'uuid4: {faker.uuid4()}')

The example generates three fake hashes and one UUID value.

$ python hash_uuid.py
md5: 16bbe790abb39d83f51b33a1aaddadd7
sha1: ce418346a9fe2518f8d360d754b8bed71c667bfd
sha256: 52fa1d5b849db4f7ef010d81190bd9921e28d075669c6019d1d95110fe017b96
uuid4: 5321dcad-949c-4d80-b4a5-d1350d8e5729

Faking internet related data

Faker has several methods for faking internet related data.

internet.py
from faker import Faker

faker = Faker()

print(f'Email: {faker.email()}')
print(f'Safe email: {faker.safe_email()}')
print(f'Free email: {faker.free_email()}')
print(f'Company email: {faker.company_email()}')

print('------------------------------------')

print(f'Host name: {faker.hostname()}')
print(f'Domain name: {faker.domain_name()}')
print(f'Domain word: {faker.domain_word()}')
print(f'TLD: {faker.tld()}')

print('------------------------------------')

print(f'IPv4: {faker.ipv4()}')
print(f'Private IPv4: {faker.ipv4_private()}')
print(f'IPv6: {faker.ipv6()}')
print(f'MAC address: {faker.mac_address()}')

print('------------------------------------')

print(f'URL: {faker.url()}')
print(f'Slug: {faker.slug()}')
print(f'User agent: {faker.user_agent()}')

The example shows various internet related data, including emails, domain names, IP addresses, URLs, slugs, and user agents. The safe_email method uses the reserved example.* domains, so the generated addresses cannot belong to real people.

$ python internet.py
Email: samuelbond@example.com
Safe email: pcannon@example.com
Free email: jonesstephanie@hotmail.com
Company email: geraldkelly@gonzalez.com
------------------------------------
Host name: desktop-11.miller-lambert.com
Domain name: rodriguez.com
Domain word: benitez
TLD: com
------------------------------------
IPv4: 157.150.110.47
Private IPv4: 192.168.2.123
IPv6: eca7:50f4:3901:91aa:3fa:1586:5bef:b8ed
MAC address: f0:81:d2:5f:47:9d
------------------------------------
URL: https://www.case.com/
Slug: help-teacher-course
User agent: Mozilla/5.0 (iPad; CPU iPad OS 17_4_1 like Mac OS X) AppleWebKit/533.2 (KHTML, like Gecko) CriOS/55.0.883.0 Mobile/81P534 Safari/533.2

Faking date and time

Faker has plenty of methods for faking date and time values.

date_time.py
from faker import Faker

faker = Faker()

print(f'Date of birth: {faker.date_of_birth(minimum_age=18, maximum_age=65)}')
print(f'Century: {faker.century()}')
print(f'Year: {faker.year()}')
print(f'Month: {faker.month()}')
print(f'Month name: {faker.month_name()}')
print(f'Day of week: {faker.day_of_week()}')
print(f'Day of month: {faker.day_of_month()}')
print(f'Time zone: {faker.timezone()}')
print(f'AM/PM: {faker.am_pm()}')

The example shows methods for the date of birth, date and time parts, time zones, and AM/PM. The minimum_age and maximum_age parameters bound the age of the person.

$ python date_time.py
Date of birth: 1961-05-27
Century: XV
Year: 2010
Month: 08
Month name: April
Day of week: Friday
Day of month: 12
Time zone: America/Guyana
AM/PM: PM

Recent dates and time series

The next example generates values in the current century, decade, year, or month, and a time series.

date_time2.py
from datetime import timedelta

from faker import Faker

faker = Faker()

print(f'Datetime this century: {faker.date_time_this_century()}')
print(f'Datetime this decade: {faker.date_time_this_decade()}')
print(f'Datetime this year: {faker.date_time_this_year()}')
print(f'Datetime this month: {faker.date_time_this_month()}')

print('-------------------------')

print(f'Date this century: {faker.date_this_century()}')
print(f'Date this decade: {faker.date_this_decade()}')
print(f'Date this year: {faker.date_this_year()}')
print(f'Date this month: {faker.date_this_month()}')

print('-------------------------')

series = faker.time_series(start_date='-12d', end_date='now',
                           precision=timedelta(days=2))

for timestamp, value in series:
    print(timestamp, value)

The time_series method yields pairs of a timestamp and a random value. The precision parameter sets the step between the timestamps; relative dates such as -12d mean twelve days ago.

$ python date_time2.py
Datetime this century: 2002-09-06 00:29:44.646039
Datetime this decade: 2021-12-18 06:54:31.362709
Datetime this year: 2026-04-13 23:32:39.677387
Datetime this month: 2026-10-09 04:39:50.258099
-------------------------
Date this century: 2010-10-17
Date this decade: 2023-11-04
Date this year: 2026-05-15
Date this month: 2026-10-10
-------------------------
2026-10-18 20:53:44 80381.59040440954
2026-10-20 20:53:44 88973.72940411918
2026-10-22 20:53:44 110168.04424437074
2026-10-24 20:53:44 104294.88847840732
2026-10-26 20:53:44 101104.33042316716
2026-10-28 20:53:44 145529.7404315011

Date ranges

The third example shows methods for various datetime formats, for values in a chosen range, and for future or past values.

date_time3.py
from faker import Faker

faker = Faker()

print(f'Unix time: {faker.unix_time()}')
print(f'Datetime: {faker.date_time()}')
print(f'iso8601: {faker.iso8601()}')
print(f'Date: {faker.date()}')
print(f'Time: {faker.time()}')

print('-------------------------')

print(f"Datetime between: {faker.date_time_between(start_date='-15y', end_date='now')}")
print(f"Date between: {faker.date_between(start_date='-30d', end_date='today')}")

print('-------------------------')

print(f'Future datetime: {faker.future_datetime()}')
print(f'Future date: {faker.future_date()}')
print(f'Past datetime: {faker.past_datetime()}')
print(f'Past date: {faker.past_date()}')

The date_time_between and date_between methods generate values in a given range. The future and past methods generate values within 30 days from now by default.

$ python date_time3.py
Unix time: 1444940762.0257442
Datetime: 1991-02-10 19:30:34.072765
iso8601: 2011-08-31T04:00:44.342913
Date: 1997-03-08
Time: 23:09:58
-------------------------
Datetime between: 2017-05-05 19:30:59.724761
Date between: 2026-10-23
-------------------------
Future datetime: 2026-11-17 10:57:21.097191
Future date: 2026-11-12
Past datetime: 2026-10-28 21:39:56.542747
Past date: 2026-09-30

Seeding the generator

Tests need reproducible data. The Faker.seed class method seeds the shared random generator, so the same sequence of calls produces the same values.

seeding.py
from faker import Faker

Faker.seed(4321)
faker = Faker()

print(faker.name(), faker.city(), faker.random_int(1, 100))

We run the program twice and get the same output. The values depend on the order of the calls and may change between Faker versions.

$ python seeding.py
Jason Brown Lake Michael 87
$ python seeding.py
Jason Brown Lake Michael 87

Unique values

The unique proxy ensures that a method does not return the same value twice.

unique_values.py
from faker import Faker
from faker.exceptions import UniquenessException

faker = Faker()

numbers = [faker.unique.random_int(1, 5) for _ in range(5)]
print(sorted(numbers))

try:
    faker.unique.random_int(1, 5)
except UniquenessException as e:
    print(f'error: {e}')

faker.unique.clear()
print(faker.unique.random_int(1, 5) in range(1, 6))

emails = {faker.unique.email() for _ in range(1000)}
print(len(emails))

We draw all five numbers between one and five. Another call cannot find a new value and raises UniquenessException after a thousand attempts. The clear method forgets the values seen so far. We also generate a thousand unique emails, for instance for a table with a unique column.

$ python unique_values.py
[1, 2, 3, 4, 5]
error: Got duplicated values after 1,000 iterations.
True
1000

Custom providers

We can add our own providers to the generator.

custom_provider.py
from faker import Faker
from faker.providers import BaseProvider, DynamicProvider


class BookProvider(BaseProvider):

    genres = ['fantasy', 'crime', 'history', 'science fiction', 'poetry']

    def genre(self):
        return self.random_element(self.genres)

    def isbn_like(self):
        return self.numerify('978-##-####-###-#')


language_provider = DynamicProvider(
    provider_name='language',
    elements=['Python', 'Go', 'Rust', 'C#', 'Java'],
)

faker = Faker()
faker.add_provider(BookProvider)
faker.add_provider(language_provider)

for _ in range(3):
    print(f'{faker.catch_phrase()} | {faker.genre()} | {faker.isbn_like()}')

print(faker.language())

A provider is a subclass of BaseProvider; its public methods become methods of the generator. The provider can use helpers such as random_element and numerify. For a simple list of values, a DynamicProvider is enough; its provider_name becomes the method name.

$ python custom_provider.py
Managed zero-defect forecast | fantasy | 978-38-0132-195-4
Down-sized uniform model | fantasy | 978-66-8149-710-7
Profound asymmetric synergy | fantasy | 978-79-7310-457-5
Go

Generating CSV data

Together with the csv module, we create a new CSV file with fake data.

fake_csv.py
import csv

from faker import Faker

faker = Faker()

with open('users.csv', 'w', newline='') as f:

    fieldnames = ['id', 'first_name', 'last_name', 'occupation']
    writer = csv.DictWriter(f, fieldnames=fieldnames)

    writer.writeheader()

    for i in range(1, 101):
        writer.writerow({'id': i, 'first_name': faker.first_name(),
                         'last_name': faker.last_name(),
                         'occupation': faker.job()})

The data contains an id, a first name, a last name, and a job title. The data is written to the users.csv file.

fieldnames = ['id', 'first_name', 'last_name', 'occupation']
writer = csv.DictWriter(f, fieldnames=fieldnames)

We use the dictionary writer with the given field names.

writer.writeheader()

We write the header line.

for i in range(1, 101):
    writer.writerow({'id': i, 'first_name': faker.first_name(),
                     'last_name': faker.last_name(),
                     'occupation': faker.job()})

We generate 100 users. Each user is written to the file with the writerow method. Some job titles contain commas; the writer quotes them.

$ python fake_csv.py
$ head -5 users.csv
id,first_name,last_name,occupation
1,Andrew,Mcgee,"Lecturer, further education"
2,Melissa,Durham,"Therapist, nutritional"
3,John,Green,Clinical research associate
4,April,Miller,Electronics engineer
$ wc -l users.csv
101 users.csv

Generating XML data

In the following example, we generate XML data with Faker and a Jinja template. The XML file will contain users.

$ pip install jinja2

The XML generator

The program creates the users and renders them with the template.

fake_xml.py
from dataclasses import dataclass

from faker import Faker
from jinja2 import Environment, FileSystemLoader


@dataclass
class User:
    first_name: str
    last_name: str
    occupation: str


faker = Faker()

users = [User(faker.first_name(), faker.last_name(), faker.job())
         for _ in range(3)]

env = Environment(loader=FileSystemLoader('templates'), autoescape=True,
                  trim_blocks=True, lstrip_blocks=True,
                  keep_trailing_newline=True)

template = env.get_template('users.xml.j2')
output = template.render(users=users)

with open('users.xml', 'w', encoding='utf-8') as f:
    f.write(output)

The program generates a list of three users, stored in a dataclass. The list is passed to the Jinja template, which is located in the templates directory. The generated content is written to the users.xml file.

env = Environment(loader=FileSystemLoader('templates'), autoescape=True,
                  trim_blocks=True, lstrip_blocks=True,
                  keep_trailing_newline=True)

With autoescape=True, characters such as & in the data are escaped, so the XML stays well-formed. The trim_blocks and lstrip_blocks options remove the whitespace left by the template tags.

templates/users.xml.j2
<?xml version="1.0" encoding="UTF-8"?>
<users>
    {% for user in users %}
    <user id="{{ loop.index }}">
        <firstname>{{ user.first_name }}</firstname>
        <lastname>{{ user.last_name }}</lastname>
        <occupation>{{ user.occupation }}</occupation>
    </user>
    {% endfor %}
</users>

In the template, we use the for directive to process the list of users. The loop.index variable holds the iteration number, starting from one.

$ python fake_xml.py
$ cat users.xml
<?xml version="1.0" encoding="UTF-8"?>
<users>
    <user id="1">
        <firstname>Theresa</firstname>
        <lastname>Bridges</lastname>
        <occupation>Development worker, international aid</occupation>
    </user>
    <user id="2">
        <firstname>Nicholas</firstname>
        <lastname>Barnes</lastname>
        <occupation>Surveyor, building</occupation>
    </user>
    <user id="3">
        <firstname>Joel</firstname>
        <lastname>Hill</lastname>
        <occupation>Clinical cytogeneticist</occupation>
    </user>
</users>

Source

Faker documentation

In this article we have used Python Faker to generate fake data.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.