Hardcoded credentials, fixed product IDs, and identical payloads on every request are the hallmark of a naive load test. Real users are not identical. They have different accounts, different shopping carts, different search terms. CSV Data Set Config is how you feed that variety into JMeter — one external file, many virtual users, each pulling their own unique data.
How CSV Data Set Config works
CSV Data Set Config reads rows from a CSV file and maps the values to JMeter variables. Each JMeter thread reads the next available row when it starts a new iteration, and those variable values are available to every sampler, assertion, and extractor in scope for that iteration.
Add it via right-click → Add → Config Element → CSV Data Set Config. Place it at Thread Group level so all samplers in the group share the same data file.
The CSV file
Create a plain text file alongside your .jmx file. No header row is required — variable names are defined in the config element, not the file.
alice@test.com,Pass123,admin
bob@test.com,Pass456,user
charlie@test.com,Pass789,user
diana@test.com,Pass000,member
eve@test.com,PassXXX,userIf your file has a header row, you can either skip it manually (delete it from the file) or check First line is column names in the config element and leave the Variable Names field blank — JMeter reads the column names from the file itself.
Configuration fields
Filename: path to the CSV file. Relative paths resolve from the directory where the .jmx file is saved. An absolute path works but breaks portability — prefer relative paths.
File Encoding: leave as UTF-8 unless your data contains non-ASCII characters that require a specific encoding.
Variable Names: comma-separated list matching the columns in order. With the file above: email,password,role. Each name becomes a ${variable} available to samplers.
Delimiter: , for standard CSV. Use \t for tab-separated files.
Allow Quoted Data: check this if any CSV values are wrapped in quotes (for example, values that contain commas: "Smith, John").
Recycle on EOF: what happens when JMeter reaches the last row:
True— loop back to the first row and continue. Use when you have fewer rows than total iterations.False— stop reading new rows. Threads that need a row get an empty variable.
Stop Thread on EOF: when Recycle on EOF is False, stop the thread when no rows remain. Use this for "each user runs exactly once" scenarios — when the CSV runs out, the thread exits cleanly.
Sharing Mode: the most important field for parallel tests.
Sharing modes explained
Step 1 of 5
All threads
One shared file pointer advances atomically across all threads. Thread 1 gets row 1, Thread 2 gets row 2, Thread 3 gets row 3. Each row is used by exactly one thread per read cycle. Best for distributing unique credentials across all VUs.
Using variables in samplers
Once the CSV Data Set Config is configured, reference the variables anywhere in the test plan using ${variableName}:
In a POST body:
{
"email": "${email}",
"password": "${password}"
}In a URL path:
/api/users/${userId}/orders
In a Header Manager:
Authorization: Bearer ${apiKey}
In an assertion condition:
${__groovy("${role}" == "admin")}Generating test data
For serious load tests you need hundreds or thousands of rows. Do not create them by hand.
Python with Faker:
from faker import Faker
import csv
fake = Faker()
with open('users.csv', 'w', newline='') as f:
writer = csv.writer(f)
for i in range(10000):
writer.writerow([
fake.email(),
fake.password(length=12),
fake.random_element(['admin', 'user', 'member'])
])Quick shell one-liner for sequential IDs:
for i in $(seq 1 1000); do echo "user${i}@test.com,Pass${i},user"; done > users.csvFor data that must correspond to real records in your test database — actual user IDs, product SKUs, order numbers — export it from the database directly:
COPY (SELECT email, 'TestPass123', role FROM users WHERE active = true LIMIT 5000)
TO '/tmp/test_users.csv' WITH (FORMAT CSV);Multiple CSV files
Use multiple CSV Data Set Config elements for different data types:
Thread Group
├── CSV Data Set Config — users.csv (email, password)
├── CSV Data Set Config — products.csv (productId, productName)
└── HTTP Request — login with ${email}, browse ${productName}
Each config element runs independently, advancing its own pointer. Variable names must not overlap between configs.
⚠️ Common mistakes
- Using "Current thread" when you need unique data. If sharing mode is "Current thread", every thread reads from row 1 independently — meaning all threads use the same credentials, causing login collisions and corrupted session state. Use "All threads" when each VU must have a unique row.
- CSV file not found at runtime. JMeter resolves relative paths from the
.jmxfile's directory. If you move the.jmxwithout moving the CSV, the path breaks. Always keep CSV files in the same directory as the test plan, or use a configurable base path via a JMeter property. - Not enough rows for the test size. A 100-user, 50-iteration test needs 5,000 unique rows to avoid data collisions. With Recycle on EOF = True, you get rotation — thread 1 and thread 101 share row 1. Whether collision matters depends on your application — if two users logging in with the same credentials causes server-side conflict (account locking, duplicate session), this breaks the test.
🎯 Practice task
Build a data-driven login test.
- Create
users.csvin the same directory as your.jmxfile with 10 rows of test data in the format:email,password. - Add a CSV Data Set Config to your Thread Group: filename =
users.csv, variable names =email,password, sharing mode = All threads, Recycle on EOF = True. - Add an HTTP Request for login. In the Body Data tab:
{"email":"${email}","password":"${password}"}. AddContent-Type: application/jsonvia Header Manager. - Run with 5 users, 2 loops (10 total iterations). In View Results Tree, click each request and check the Request tab — confirm each iteration uses a different row from the CSV.
- Change the loop count to 1 and set Stop Thread on EOF = True with Recycle on EOF = False. Run with 10 users. Confirm the test stops cleanly after all 10 rows are consumed.