Correlation in JMeter: Catching the Values the Server Hands You
A deep, plain-English guide to capturing dynamic values from server responses and feeding them into later requests, covering every extractor, the workflow that finds and fixes dynamic values, and the traps that make a replayed test fail or, worse, look successful while doing nothing useful.
Imagine checking in at a hotel. At the front desk you receive a room key card with a code that the hotel computer created a moment ago, just for you and just for this stay. If you photocopied someone else’s old card and tried it on your door, nothing would happen, because that code belongs to a different guest on a different night. To get into your room you must take the card the hotel hands you today and use that one.
Modern applications behave exactly like that hotel. When a virtual user signs in, the server hands back a session token, a security code or an identifier created especially for that user at that moment. Every later request must present that same value. A test that merely replays what a recording captured last Tuesday presents the old card, and the server rightly refuses. The skill of catching the fresh value and presenting it again is called correlation. This guide explains it from zero knowledge, tool by tool, and teaches how to find, capture, verify and maintain correlated values.
1What Correlation Is and Why It Exists
We begin with the problem it solves, because the tools only make sense once the problem is clear.
The replay problem
The quickest way to build a test is to record a real journey in a browser and replay it with many virtual users. The recording captures every value exactly as it was that day: the session identifier, the security token on the form, the order number the server produced. When the test replays, it sends those frozen values. Most of them are now wrong, because the server generates fresh ones for every session.
The solution in one sentence
Correlation means capturing a dynamic value from a server response, storing it in a variable, and using that variable in the later requests that need it, so every virtual user presents the value that the server gave to that user.
Why it matters for honest results
If correlation is missing, the server rejects or redirects the requests. The test then measures how quickly the server says no, which is usually very fast, so the report shows excellent response times for a system that never did any real work. Correct correlation is therefore not a convenience; it is what makes a load test measure the real application.
Think of a cloakroom ticket. You hand over your coat and receive a numbered ticket. To get the coat back, you must present that exact ticket, not a number you remembered from yesterday. Correlation is the habit of holding on to the ticket the server just gave you.
2Core Concepts You Need First
A handful of terms appear throughout this guide, and learning them now makes everything easier.
Dynamic Value
A value that the server generates freshly, often for each user or each request, and that therefore cannot be typed into a test in advance.
Post-Processor
An element that runs after a sampler finishes and works with its response. Extractors are post-processors.
Extractor
A post-processor that pulls a piece of the response, such as a token, and stores it in a variable.
Variable
A named value held privately by each virtual user. Later requests refer to it by name.
Reference
A dollar sign followed by a name in curly braces. JMeter replaces it with the stored value when a request is built.
Session
The ongoing conversation between one user and the application after sign-in, usually tracked by a cookie or a token.
Default Value
The text an extractor stores when it finds nothing. A recognisable default makes failures visible instead of silent.
Scope
The set of samplers an element applies to, determined by where it sits in the plan tree.
Every virtual user has its own variables. A token extracted by user number five is invisible to user number six, which is exactly what correlation needs, since each user holds a different token.
3Correlation Versus Parameterisation
Two ideas are constantly confused, and mixing them up leads to the wrong fix.
| Aspect | Correlation | Parameterisation |
|---|---|---|
| Where the value comes from | The server’s response during the run | Your own test data, such as a file |
| Who decides the value | The application | The tester |
| Typical examples | Session tokens, form security codes, order numbers | Usernames, passwords, search words, product codes |
| Main tools | Extractors | Data files, counters, random elements |
| Known before the test? | No | Yes |
A simple test to tell them apart
Ask whether you could have written the value into a spreadsheet before the test started. A username could be listed in advance, so it is a parameter. A token that the server creates at sign-in could never be listed in advance, so it needs correlation.
They work together
Most real journeys use both. The username and password come from a data file, and the session token that results from signing in is captured by an extractor. Parameterisation supplies what you decide; correlation carries what the server decides.
Trying to fix a rejected token by adding it to a data file. Server-generated values change every session, so a file of old tokens simply supplies more expired ones.
4Where Dynamic Values Hide
Knowing the usual suspects makes finding them much faster.
Session Identifiers
Often carried automatically in cookies, but sometimes placed in the address or in hidden form fields, where they need explicit capture.
Anti-Forgery Tokens
Hidden form values or headers that prove a request came from a page the server itself served. They change per session and sometimes per request.
View State and Event Validation
Long hidden fields used by some web frameworks to carry page state back to the server. They are large, change constantly and must be returned exactly.
Access Tokens
Values returned by a sign-in or authorisation step and sent in a header on every later call. They usually expire after a set time.
Generated Identifiers
Order numbers, record identifiers and basket identifiers created by the server and used in follow-up requests.
Timestamps and Nonces
Values that prove freshness or prevent replay. Some are generated by the client, others handed over by the server.
Redirect Addresses
Addresses containing one-time codes, returned in a response header and followed by the browser.
Dynamic Field Names
Occasionally even the names of form fields change per session, so both the name and the value need capturing.
Dynamic values appear in addresses, query parameters, form bodies, headers, and cookies. Scan all five places when you compare a recording with a replay.
5How Correlation Works Inside
The mechanism is simple, and seeing the order of events explains most correlation bugs.
The order of events
A sampler sends its request and receives the response. Then, before the thread moves on, every post-processor in the sampler’s scope runs in order and looks at that response. An extractor finds its value and stores it under a variable name in the thread’s private variables. The next sampler is then built: JMeter replaces every reference with the current value of the variable, and sends the request carrying the fresh value.
The key consequence
An extractor can only supply values to samplers that run after it. A token captured in step four is useless to step two. Correlation is therefore always a matter of finding the first response in which a value appears and extracting it there.
sequenceDiagram
participant V as Virtual User
participant S1 as Sign-in Sampler
participant X as Extractor
participant Srv as Server
participant S2 as Next Sampler
V->>S1: Send sign-in request
S1->>Srv: Request
Srv-->>S1: Response with fresh token
S1->>X: Hand over response
X->>V: Store token in user's variable
V->>S2: Build next request using the variable
S2->>Srv: Request carries the fresh token
Srv-->>S2: Accepted
Picture a relay race. The runner finishing one leg hands over a baton that carries a message written moments ago. The next runner cannot invent the message; they can only carry the one they were handed. The extractor is the handover.
Believing JMeter knows which values are dynamic and tracks them automatically. It does not. You must identify each dynamic value and tell JMeter where to find it.
6The Extractor Family at a Glance
JMeter offers several extractors, and each suits a different kind of response.
| Extractor | Best For | How It Finds the Value |
|---|---|---|
| Regular Expression Extractor | Any text: pages, headers, addresses | A pattern with a capture group |
| Boundary Extractor | Simple text with clear surrounding markers | Text immediately to the left and right of the value |
| JSON Extractor | JSON responses from interfaces and services | A path that walks down the structure |
| JSON JMESPath Extractor | JSON needing filtering or reshaping | A query expression in a different JSON query language |
| CSS Selector Extractor | HTML pages, especially hidden form fields | A selector naming an element and an attribute |
| XPath Extractor | XML and well-formed HTML | A path through the document tree |
| Script post-processor | Complex logic no simple extractor expresses | Code you write |
flowchart TD
A[What is the response?] --> B{JSON?}
B -- Yes --> C[JSON Extractor]
A --> D{HTML page?}
D -- Yes --> E[CSS Selector Extractor or Boundary Extractor]
A --> F{XML?}
F -- Yes --> G[XPath Extractor]
A --> H{Header, address or plain text?}
H -- Yes --> I[Boundary or Regular Expression Extractor]
A --> J{Logic too complex?}
J -- Yes --> K[Script post-processor]
Use the most specific extractor available for the format of the response. A JSON response is read best by the JSON extractor; a hidden form field is read best by the selector extractor. Reach for regular expressions when nothing simpler fits.
7The Regular Expression Extractor in Depth
It is the most flexible extractor and the most commonly misused, so each field deserves explanation.
Apply To
Chooses which part of the sampler’s result to search: the main sample, its sub-samples such as embedded resources and redirects, both, or a named variable.
Field to Check
Chooses where to look: the body, the body with HTML escapes undone, the body as a document, response headers, request headers, the address, the response code or the response message.
Reference Name
The name of the variable to create. Choose a meaningful name, because it will appear in later requests.
Regular Expression
The pattern. It normally contains text before the value, a capture group for the value itself and text after it.
Template
Says how to build the stored value from the captured groups. The first group is the usual choice.
Match Number
Chooses which match to keep: a specific position, a random one, or all matches, which creates numbered variables.
Default Value
The text stored if nothing matches. Always set one that clearly signals failure.
Use Empty Default
A checkbox that allows an intentionally empty default, for cases where absence is normal.
The shape of a good pattern
A dependable pattern has three parts: a short, stable piece of text that always appears immediately before the value, a capture group that matches the value itself using the shortest possible match, and a short, stable piece of text that always follows the value. Everything else in the page is ignored. The goal is to anchor on text that identifies the value’s location without including anything that changes.
When the match number asks for all matches, JMeter creates numbered variables for each, plus a count. This is the basis for looping over lists, covered later in this guide.
Leaving the default value empty. When extraction fails, nothing signals the failure, and the next request quietly goes out with a missing token.
8Writing Patterns That Survive Change
A pattern that works today and breaks next week wastes more time than no pattern at all.
Principles
Anchor on stable neighbours
Use the name of the hidden field or the key of the property, not its position on the page or its line number.
Match the shortest value
Use the lazy form of the wildcard so the capture stops at the first right-hand marker rather than running to the last one on the page.
Keep it short
Long patterns that copy whole lines of the page break when anything nearby changes, such as spacing or attribute order.
Allow for formatting variety
Allow optional spaces and either kind of quote where the page might vary, if you have seen such variety.
Escape special characters
Characters with special meaning in patterns, such as dots and brackets, must be escaped when they are meant literally.
Test against several responses
Try the pattern on responses from different users and different moments before trusting it.
Problem
A pattern copies an entire line of the page, including attribute order, spacing and unrelated attributes, and captures the token in the middle.
Why It’s Harmful
Any harmless change to the page, such as reordering attributes or adding a class, breaks the match. The token is silently not captured and every later request fails.
Correct Approach
Anchor on the stable field name immediately before the value and the closing quote immediately after, or use the selector extractor, which understands the page structure.
9The Boundary Extractor: Simpler Than Patterns
Many correlation jobs need only two pieces of fixed text, and there is an extractor built for exactly that.
The idea
The Boundary Extractor asks for two things: the text that sits immediately to the left of the value and the text that sits immediately to the right. Whatever lies between them is captured. There is no pattern language to learn, no special characters to escape and no risk of an over-greedy match.
When it shines
It is ideal for simple, predictable markers: a value between two quotes after a known field name, a number after a label and before a comma, or a code between two known characters in a header. Because it avoids pattern syntax, it is also easier for colleagues to read and maintain.
| Aspect | Boundary Extractor | Regular Expression Extractor |
|---|---|---|
| Learning effort | Very low | Moderate to high |
| Flexibility | Fixed left and right text only | Full pattern matching |
| Risk of mistakes | Low | Higher, especially with wildcards |
| Readability for others | High | Depends on pattern complexity |
| Best use | Clear markers on both sides | Variable surroundings or several groups |
Try the Boundary Extractor first for text responses. Move to regular expressions only when the markers vary or when you need to combine several captured parts into one value.
10The JSON Extractor and the JMESPath Extractor
Most modern interfaces answer in JSON, and a JSON-aware extractor is far safer than treating the response as plain text.
How JSON extraction works
JSON describes data as nested named fields and ordered lists. The JSON Extractor takes a path that starts at the root of the response and walks down through field names and list positions to the wanted value. Because it understands the structure, it is unaffected by spacing, line breaks or the order of unrelated fields, all of which break text patterns.
Useful options
Variable Name
The variable that will hold the result. When several values match, numbered variables are created as well.
Path Expression
The route to the value, written with field names separated by dots. Filters can select items in a list by a property.
Match Number
Chooses one item, a random item or all items when a path returns a list.
Compute Concatenation
Joins all matches into one variable, useful when a request needs a comma-separated list of identifiers.
Default Value
The text stored if the path finds nothing. Set a clear failure marker, as with every extractor.
The JMESPath alternative
A companion extractor uses a different query language that can filter, project and reshape JSON in a single expression. It is helpful for complicated structures, such as picking the identifier of the first item whose status equals a given word. For ordinary one-value extraction the plain JSON extractor is easier to read.
Using a text pattern on a JSON response. It works until the service changes formatting or field order, and then fails without warning. Let a JSON-aware tool read JSON.
11CSS Selector and XPath Extractors for Pages and XML
Web pages and XML documents have structure, and extractors that read structure are more dependable than text patterns.
The CSS Selector Extractor
A page is a tree of elements. The CSS Selector Extractor takes a selector that names an element, for example a hidden input with a particular name, and an attribute name whose value you want, usually the value attribute. It finds the element wherever it sits and returns the attribute. Reordered attributes, extra classes and changed spacing do not matter, because the extractor reads the page as a document.
The XPath Extractor
For XML responses, such as older web service replies, the XPath Extractor takes a path through the document tree and returns the text or attribute found there. It has options to treat imperfect page markup as a document and to handle namespaces, which are labels that qualify element names in XML.
Hidden form fields
The classic use: capture the security token or state field from a form page by selecting the hidden input with that name and reading its value.
Links and identifiers on a page
Select the link for the first product in a list and read its address attribute, then use the identifier in a following request.
XML service replies
Use a path to pick out the session identifier or reference number from an XML reply, with namespaces declared if the document uses them.
| Situation | Preferred Extractor | Reason |
|---|---|---|
| Hidden form field on a page | CSS Selector Extractor | Reads the element and its attribute directly |
| Value inside a script block in a page | Boundary or Regular Expression Extractor | Script text is not page structure |
| XML service reply | XPath Extractor | Path through the document tree |
| Mixed or malformed markup | Boundary Extractor | Does not depend on valid structure |
View Results Tree has testing modes for selectors and paths. Paste your expression, see what it returns on a real response and refine it before putting it into the plan.
12Headers, Addresses and Redirects
Not every dynamic value lives in the body, and some live in a response that JMeter hides by default.
Values in response headers
Some systems return tokens, identifiers or the address of a newly created item in a response header. An extractor can be told to search the response headers instead of the body, so a header value can be captured just like a body value.
Redirects hide the middle step
When a server answers a request with a redirect, a browser silently follows it. By default, JMeter’s web request element can do the same. If the dynamic value is carried in the redirect itself, such as a one-time code in the address of the next page, the automatic following hides it, and the extractor only sees the final page.
The two redirect settings
Redirect Automatically
The underlying connection layer follows redirects invisibly, so JMeter never sees the intermediate response. Extractors cannot capture anything from it.
Follow Redirects
JMeter follows redirects itself and records each step as a sub-sample, so extractors set to include sub-samples can read headers and bodies of intermediate steps.
Turn Both Off
The redirect response itself becomes the main sample. You can read its address header and send the next request yourself with full control.
Apply To Sub-Samples
When following redirects, choose whether the extractor searches the main sample, the sub-samples or both.
Searching for a value in the final page when it was only present in an intermediate redirect. The extractor finds nothing and the default value flows into later requests.
13Cookies: When You Do Not Need Correlation
A large share of session handling is automatic, and knowing this saves you from needless extractors.
The cookie manager does it for you
When a server sets a cookie, the HTTP Cookie Manager stores it and sends it back on later requests to the same site, exactly as a browser would. Many session identifiers travel this way, so a plan containing a cookie manager often needs no explicit correlation for the session itself. Without a cookie manager, the session is lost after the first request.
When explicit capture is still needed
Cookies cover only values the server sets as cookies. A token returned in a response body, a code placed in a hidden form field or a value in a header still needs an extractor. Some applications send the same session information in both a cookie and a field or header, and the extra copy must be correlated.
| Where the Value Arrives | Automatic? | Action |
|---|---|---|
| Set as a cookie by the server | Yes, with a cookie manager | Add one cookie manager to the plan |
| Hidden field in a form page | No | Extract and send with the form |
| JSON field in a response | No | Extract with a JSON extractor |
| Response header | No | Extract from headers |
| Address of a redirect | No | Disable automatic redirects and extract |
A cookie manager can be told to clear cookies at each iteration. That is right when each iteration should be a new visitor, and wrong when a session obtained once must last the whole test.
Building extractors for session cookies that the cookie manager already handles, or conversely, forgetting the cookie manager and wondering why every request looks signed out.
14The Correlation Workflow, Step by Step
A repeatable routine turns correlation from guesswork into a calm, mechanical task.
flowchart TD
A[Record or build the journey] --> B[Replay with one user]
B --> C{Does it succeed?}
C -- Yes --> H[Add assertions and run with several users]
C -- No --> D[Find the first failing request]
D --> E[Identify the dynamic value in it]
E --> F[Find the earlier response that supplied it]
F --> G[Add extractor and replace value with variable]
G --> B
Replay with one user
Run the recorded journey with a single thread and a detailed results viewer.
Find the first failure
Look for the earliest request that returns an error, an unexpected redirect or an error page, ignoring later failures that are only consequences.
Spot the stale value
Compare that request with the recorded original to find which sent value differs from what the server now expects.
Locate the source
Search the earlier responses for the first place the value appeared, and note its surrounding text.
Add the extractor and the reference
Attach an extractor to the sampler that returned the value and replace the frozen value in the later request with a reference to the new variable.
Replay and repeat
Run again. Each pass fixes one dynamic value, and a typical journey needs a handful of passes.
Fix one value at a time and replay after each fix. Fixing several at once makes it hard to know which change helped and which introduced a new problem.
15Finding Dynamic Values: The Two-Recording Method
The fastest way to find every dynamic value is to let the differences between two recordings reveal them.
The idea
Record the same journey twice, using different test accounts and different input where possible. Static values, such as page paths and fixed parameter names, are identical in both recordings. Dynamic values, such as tokens and identifiers, differ. Comparing the two recordings with any file comparison tool therefore highlights exactly the values that need correlation.
What to compare
Request Addresses
Identifiers and tokens embedded in paths and query strings.
Form Parameters
Hidden fields, state values and tokens in request bodies.
Request Headers
Authorisation headers and custom headers carrying generated values.
Cookies
Cookie values that differ, remembering that the cookie manager handles most of them automatically.
Separating genuine dynamics from your own input
Some differences come from the data you typed, such as different names or search words, and belong to parameterisation. Others come from the server and belong to correlation. If a value appears in a response before you typed anything, the server produced it. If it matches something you entered, it is your input.
For each differing value, also search the earlier responses of the second recording for the same text. Finding it in an earlier response tells you exactly where the extractor belongs.
Recording twice at the same second with the same data, or on a system that reuses values. Some differences then disappear and a truly dynamic value looks static until load reveals it.
16Verifying Extraction with Testers and Debug Elements
A correlated value that is never checked is a hope, not a fix.
View Results Tree testing modes
The results viewer offers modes for testing patterns, selectors, paths and boundaries against a real response. You paste an expression, see matches highlighted and adjust until it returns exactly the wanted value.
Resolved request inspection
The viewer’s request tab shows the final request after references are replaced. A leftover reference sign means the variable did not exist at that moment, and the default text means extraction failed.
Debug Sampler
Placed after the extractor, it records every variable and property for the current user, showing precisely what was captured.
Debug Post-Processor
Attached to a specific sampler, it records the variables after that sampler’s extractors run, without adding a separate request.
Two-user comparison
Run two users and confirm that each captured a different value, proving that variables are private and extraction is working per user.
Debug elements and detailed viewers help in development and hurt at scale. Disable them before real load, including runs from the command line.
17Default Values and Detecting Failure
Extraction will sometimes fail, and the test must notice when it does.
Why failure is silent by nature
An extractor that finds nothing is not an error from JMeter’s point of view. The request that created the response may have succeeded perfectly. The failure surfaces later, when a request carries a missing or stale value and the server complains. By then, the cause is several steps behind.
Defaults as tripwires
Setting a distinctive default text, such as a phrase that says the token was not found, turns silent failure into a visible sign. The default shows up in the resolved request and in the server’s complaint, pointing straight at the extractor that failed.
Assertions that check the extraction
A response assertion can examine the stored variable and fail the sample if it still holds the default text. This makes the problem appear at the right place, in the right row of the report, and with a clear failure message. Pair it with a rule that stops a thread whose critical extraction failed, so it does not flood the results with consequent errors.
Choose a recognisable default
Use words that cannot occur in real data and that name the variable.
Assert on the response that supplies it
Check the response itself for the expected marker, so a wrong page is caught before extraction.
Assert on the variable
Fail the sample if the variable still holds the default text.
Decide what happens next
Configure the thread to stop, or to start the next iteration, when a critical value is missing.
Judging correlation by the absence of errors in the first request after the extractor. Some servers accept a missing token on that call and reject it later. Verify the whole journey, not just the next step.
18Multiple Matches: Lists, Loops and Random Choices
Many pages contain lists, and realistic users pick from them.
Capturing every match
When an extractor is told to keep all matches, it creates one variable per match, numbered from one, plus a variable that holds the count. A page listing twenty products yields twenty identifiers ready to use, along with the number twenty.
Looping over the list
A ForEach Controller walks through such numbered variables one by one. You give it the common name prefix, the start and end positions and an output variable name, and on each pass the output variable holds the next identifier. Requests inside the loop then refer to the output variable, for example to open each product in turn.
Picking one at random
Real users choose different items. You can ask the extractor for a random match, or capture all and choose a position with a random-number function. The second approach lets you control the range and reuse the same chosen item across several requests.
flowchart LR
A[Page lists products] --> B[Extractor keeps all matches]
B --> C[Numbered variables and a count]
C --> D{Need all or one?}
D -- All --> E[ForEach Controller loops over them]
D -- One --> F[Random position picks one variable]
E --> G[Requests use the current item]
F --> G
| Goal | Approach | Caution |
|---|---|---|
| Open every item once | Keep all matches and loop | Long lists create many requests; limit the range if needed |
| Open one random item | Random match or random position | Use the same chosen item for follow-up requests |
| Open the first item only | Match number one | Everyone choosing the first item warms caches unrealistically |
| Send all identifiers in one request | Concatenation option or loop that joins | Check the separator the server expects |
Always picking the first match. Every virtual user then requests the same item, the server’s cache answers instantly, and the test understates the cost of real, varied browsing.
19Tokens That Rotate, Expire and Refresh
Some values are not captured once; they change throughout the journey.
One value, many generations
Many applications issue a new anti-forgery token after every form submission, and some rotate the session identifier after login to prevent a certain class of attack. In these systems the value you captured on page two is already stale by page four. The test must capture again, from the response that replaced it, and overwrite the variable. Because an extractor writes to the same variable name each time it runs, this usually means placing an extractor after every request that issues a new generation.
Imagine a bank that gives you a fresh one-time code on a slip of paper after every transaction. The old slip is worthless the moment the new one arrives. If you keep presenting the first slip, the teller refuses you, however politely you ask. Your job is to read the newest slip every time.
Time-limited values
Access tokens in modern sign-in flows live for a limited time, often minutes. A long test with think time can easily outlive a token. Real browsers and apps handle this by using a refresh token to obtain a new access token shortly before expiry. A faithful test must do the same: record when the token was issued, check the age before each use, and call the refresh step when it is close to expiry.
Capture token and lifetime
Extract both the token and the number of seconds it remains valid from the sign-in reply.
Record the issue time
Store the moment of issue in a variable using a time function, so age can be computed later.
Check before use
Place an If Controller ahead of protected calls that compares current time with issue time plus lifetime, minus a safety margin.
Refresh when close to expiry
Inside the If Controller, call the refresh request and capture the new token, which overwrites the old variable.
Deciding whether the refresh belongs in the test
If your scenario is short, say two minutes, and the token lives for an hour, refreshing is pointless complexity. If your endurance test runs for hours, ignoring expiry will produce a wave of authorisation failures that has nothing to do with capacity. Match the test to what a real session of that length would do.
A burst of authorisation errors that begins at a suspiciously regular time after the test starts is the fingerprint of an expired token, not of a struggling server.
20Encoding Problems: When the Captured Value Looks Wrong
A value can be captured perfectly and still be rejected because of how it is written.
Why text gets disguised
Web pages and web addresses reserve certain characters for their own use. An angle bracket, an ampersand, a quotation mark or a plus sign can confuse the page or the address, so they are replaced with safe stand-ins. In a page, an ampersand may appear as a short entity code. In an address, a space or slash may appear as a percent sign followed by two digits. This is called escaping or encoding, and it is the most common reason a correct-looking token is refused.
Think of a letter in a foreign language that has been run through a telegraph. Punctuation is spelled out as words so that it survives the wire. If you copy the telegraph version onto a formal document without translating it back, the recipient sees nonsense. Encoding is the telegraph version; decoding is the translation back.
Two directions, two problems
Captured value is still escaped
The page held the token with entity codes for some characters. You captured it as written, then sent it where plain characters were expected. The server compares and finds a mismatch.
Sent value needs escaping
The captured token holds characters that are special inside an address or form body. Sent as is, the server reads them as separators and cuts the token short.
The remedies
For the first problem, the regular expression extractor can be asked to read the unescaped body of the response, which decodes entity codes before matching. For the second, JMeter offers a function that applies address encoding to a value at the moment it is used, and the parameter table in a sampler has an encode option per row. Choose one place to encode and stay consistent; encoding twice is as harmful as not encoding at all.
| Symptom | Likely Cause | Remedy |
|---|---|---|
| Token in the variable contains entity codes | Page was read in escaped form | Read the unescaped body, or decode before use |
| Server says token invalid, variable looks right | Special characters not encoded on send | Turn on the encode option or apply the encoding function |
| Token arrives cut short at a plus or equals sign | Characters read as separators | Encode the value when sending |
| Token contains unusual percent sequences twice over | Encoded twice | Remove one encoding step |
Fixing an encoding problem by editing the extracted value by hand in a debug view and re-running. The hand-edited value works once and tells you nothing about the automated path that real users take.
21Scope and Placement of Extractors
Where you put an extractor in the tree decides which responses it reads.
The attachment rule
A post-processor placed inside a sampler runs only for that sampler. Placed at the level of a controller, it runs after every sampler in that controller. Placed at the level of the thread group, it runs after every sampler in the whole group. This is the scoping rule of the test tree, and it is the source of two opposite surprises: an extractor that never fires because it is attached to the wrong request, and an extractor that fires too often and overwrites a good value with a failed one.
Consider a security guard. A guard posted at one door checks only people through that door. A guard posted at the floor entrance checks everyone entering the floor. A guard at the building gate checks everyone. Where you post the guard decides who gets checked.
Choosing the tightest scope
The safest habit is to attach each extractor directly to the one sampler whose response holds the value. It documents itself, it cannot fire elsewhere, and a reader of the tree sees the cause and the capture together. Broad scope is useful only when many samplers return the same kind of value, such as a rotating token present in every page.
Which response does it read?
Besides scope, an extractor chooses which part of a response to search: the main body, the response headers, the request address, or the whole response text. Applying it to the wrong part is a quiet way to fail. A redirect address lives in headers, not in the body; a token in the address of a followed link is in the address, not in the body.
flowchart TD
T[Thread Group] --> C[Controller]
C --> S1[Sampler One]
C --> S2[Sampler Two]
S1 --> E1[Extractor on Sampler One only]
C --> E2[Extractor on Controller: runs after each sampler inside]
T --> E3[Extractor on Thread Group: runs after every sampler]
When an extractor with a default value is placed at a broad scope, it will overwrite a good variable with the default on every response that does not contain the value. That is almost never what you want.
22Correlation Together with Controllers
Controllers change how often and in what order requests run, which affects the values they leave behind.
Inside loops
When a request sits in a loop, its extractor runs on every pass and overwrites the variable each time. That is exactly what you want for a token that changes per page, and exactly what you do not want if you meant to keep the first value for later. If you need to preserve a value across passes, copy it into a second variable before the loop continues, using a small script or a variable-setting element.
Polling until something is ready
Some applications start a job and make you ask repeatedly whether it is finished. The reply carries a status, and the test needs to keep asking until the status says done. A While Controller, with its condition reading the extracted status variable, models this. Two cautions apply: put a short pause inside the loop so you do not hammer the server, and bound the loop with a counter so a stuck job cannot trap a user forever.
This is like checking the oven. You peek, see the cake is not ready, wait a few minutes and peek again. The extractor is your eyes reading the state of the cake; the While Controller is the habit of repeating until the answer changes. The counter is the rule that you will give up and call for help after an hour.
Conditional paths
An If Controller can use an extracted value to choose a path. If the response says an account needs verification, the test follows the verification steps; otherwise it skips them. This keeps one script realistic for users in different states.
Once Only and sign-in
The Once Only Controller runs its children on the first pass of each virtual user and not again. Placed around the sign-in sequence, it makes each user log in once and reuse the captured session for all later passes. Because variables are per user, the captured token remains available on later passes. Be careful when the token expires during a long loop; the earlier chapter on refresh applies.
| Controller | Correlation Role | Watch For |
|---|---|---|
| Loop Controller | Repeat capture and reuse each pass | Later passes overwrite earlier values |
| While Controller | Poll until an extracted status changes | Needs a pause and a safety bound |
| If Controller | Choose a path from an extracted value | Condition text must match exactly what the variable holds |
| Once Only Controller | Sign in once per user | Token expiry during long runs |
| ForEach Controller | Walk through captured lists | Correct prefix and correct end position |
Writing a polling loop with no bound and no pause. If the job never completes, every virtual user spins forever at full speed and the test becomes a denial-of-service exercise against your own system.
23Sign-In Flows with State, Codes and Tokens
Modern single sign-in journeys chain several correlated values across several redirects.
The shape of the journey
In an authorisation-code style flow, your application sends the user to an identity provider carrying a random state value and sometimes a one-time challenge value. The provider shows a login form with its own hidden fields, accepts the credentials, and redirects back to your application with a short-lived code and the same state value. Your application then exchanges the code for tokens behind the scenes. Every step passes a value that must be read from the previous reply and handed to the next request.
Consider a visa process. You collect a reference number at the first office, carry it to the embassy, receive a stamped slip there, and hand the slip back at the first office to receive your permit. At each counter someone checks the paper you were given at the last one. Break the chain at any point and the permit is never issued.
sequenceDiagram
participant U as Virtual User
participant A as Application
participant I as Identity Provider
U->>A: Open protected page
A-->>U: Redirect with state value
U->>I: Follow redirect
I-->>U: Login form with hidden fields
U->>I: Submit credentials and hidden fields
I-->>U: Redirect with code and state
U->>A: Return with code and state
A-->>U: Session established
Handling it in a test
Turn off automatic redirect following on the samplers in the chain so you can read the address in each redirect reply, or leave it on and rely on recordings of every hop. Extract the state and code from the redirect address, extract hidden fields from the login form, and use each in the next request. Cookies from both the application and the provider live in the cookie manager, so make sure cookies are cleared per iteration when you intend each iteration to start unauthenticated.
Token-style replies
When the exchange step returns structured data containing an access token, the JSON extractor reads it directly. The token is then attached as an authorisation header on every later call, through a header manager that reads the variable. Because the header manager can sit at the thread-group level, one element covers all calls, while the extractor sits only on the exchange request.
Identity providers are real systems with real limits. A load test that signs in thousands of users per minute against a shared provider may be unwelcome. Agree the load with the owners, or sign in once and reuse tokens where the goal is to test your own application.
24Correlation Beyond Web Pages
The idea of reading one reply and using it in the next request is not limited to web protocols.
Database results
A database sampler can store the values from a query into variables named after result columns, or into a single object variable that holds the whole result set. A later request can use the identifier it returned, for example the number of an order that was just created. This is correlation without an extractor, because the sampler itself performs the capture when you name the result variables.
Message systems
Message-based samplers can read a message identifier or correlation identifier from a reply and use it to match a request with its response, or to pick up a specific message from a queue. The extractor family works here too, since the reply is just text with a structure.
Raw connection protocols
For plain socket traffic, a server may open a session by returning a handshake token that must be echoed on every later message. The regular expression extractor can read it from the response data, and later messages can contain the variable.
Result variable names
Name the columns whose values you want and read them by position, from the first row onward, in later requests.
Message identifiers
Capture the identifier from the reply and use it to find, acknowledge or match the right message later.
Handshake tokens
Capture a token returned at connection time and include it in each following message on that connection.
Message numbers
List, then read from the returned numbers, so each read targets a message that truly exists.
A courier delivering a package asks for a tracking number to deliver or collect the right box. Whether the box travels by road, rail or air, the tracking number rides along. The vehicle changes; the principle of carrying the reference does not.
When a protocol lacks a dedicated extractor, check whether the sampler can store the result into variables itself, or whether a script-based post-processor can read the response and set a variable.
25The Performance Cost of Extraction
Reading responses is work, and at high load that work belongs to the machine running the test.
Where the time goes
Every extractor reads the response text after the sampler completes. A pattern with careless wildcards over a very large page can take noticeable processor time. Multiply that by thousands of virtual users and the load generator itself may become the bottleneck, which distorts timings and hides the real behaviour of the system under test.
Picture a mail sorter who must read every letter completely to find one phrase. If the letters are short and he reads fast, no problem. If someone hands him a novel in every envelope, he falls behind and the whole sorting line slows, though the post office itself is perfectly healthy.
How to keep extraction cheap
Attach to the narrowest scope
An extractor on one sampler reads one response, not thousands.
Prefer boundaries over heavy patterns
Plain text boundaries are simple searches and usually cost less than patterns with nested wildcards.
Avoid saving big responses
Do not keep every response body in memory or result files during a large run; capture only what you need.
Remove debug elements
Debug samplers and result trees consume memory and screen time; switch them off before a measured run.
Watching the generator
Keep an eye on the processor and memory of the load generator during the run. If it is near its limits, the numbers you report are partly the generator’s, not the server’s. Spread the load over more generators instead of trusting a stressed one.
Leaving the result tree enabled in a large run. Besides its memory cost, it slows the tool and can make the run appear far slower than the server actually is.
26Diagnosing Correlation Failures
When a correlated script breaks, the symptoms point to the cause if you read them in order.
Start at the first wrong step
Failures cascade. A missed token on page two makes pages three through nine fail, and the later errors are noise. Walk forward from the beginning, find the first request whose response differs from what a human browser saw, and fix that one before looking further.
Think of a row of falling dominoes. The first domino to topple is the only one that matters; the rest fell because of it. A mechanic looking at the last domino would waste a day.
| Symptom | Probable Cause | Where to Look |
|---|---|---|
| Variable holds the default text | Pattern did not match | The raw response in the tree, compared with the pattern |
| Variable holds a value but the server rejects it | Encoding or stale generation | Compare the sent value with what the browser sent |
| Works for one user, fails for many | A value was hard-coded or shared | Search the script for typed-in identifiers |
| Works at low load, fails at high load | Server returns a different page under pressure | The response body of the failing sampler |
| Response is a login page | Session lost or cookie missing | Cookie manager, redirect settings |
| Variable is empty after a loop | Later pass overwrote the value | Extractor scope and loop placement |
| First extraction right, later ones wrong | Rotation not handled | Add an extractor after each issuing response |
A calm routine
Run with one user
Remove concurrency so that the evidence is clean and ordered.
Inspect the first failure
Look at the request as sent and the response as received, and compare with the recording.
Check the variable
Use a debug element to print the variable and confirm its exact content, including stray spaces.
Fix one thing, rerun
Change a single item at a time so that you learn which change mattered.
Invisible characters, such as a trailing space or line break captured with a token, make a value look right and behave wrong. Printing the variable between visible markers exposes them.
27Correlation in Graphical and Command-Line Runs
A script that works while you watch it must also work when nobody is watching.
Build in the window, run on the command line
Develop and debug correlation in the graphical tool, where result trees and debug elements are available. For measured runs, execute from the command line, which uses fewer resources and has no screen to update. Before trusting a command-line run, do a small smoke run with the same plan and check the result file for errors, since the debugging aids that caught problems earlier are now switched off.
Distributed generators
When several machines generate load, each runs its own copy of the plan and holds its own variables. Correlated values are per user and per machine, so nothing is shared by accident. However, files used for parameterisation must exist on every machine, and if each machine reads the same file from the top, different machines may use identical accounts. Split the data or configure the file reading so each machine reads a different portion.
Imagine several chefs in separate kitchens following the same recipe card. Each has their own bowls and ingredients, so their dough never mixes. But if all chefs fetch eggs from the same single carton in the shop, they might fight over the same eggs. Parameter files are that carton; correlated variables are the private bowls.
Reading the results afterwards
Configure the result file to record failure messages and response codes. A correlation failure shows up as a cluster of unexpected response codes or assertion failures beginning at one point in each user’s journey. Without this information, you see only that errors occurred, not why.
Debug aids and verbose logging that were helpful during development should be disabled for the measured run, and the plan should be reviewed once more for hard-coded values that only worked on your own machine.
28Security and Hygiene Around Captured Values
Correlation handles credentials and session keys, so the test artefacts deserve the same care as the system.
What your files may contain
Captured tokens appear in debug output, in saved response bodies, in result files and in screenshots shared during troubleshooting. A session key from a test against a shared environment can be as powerful as a real user’s. Treat result files and logs from authenticated runs as sensitive, store them in access-controlled places, and delete them when no longer needed.
A locksmith who copies keys for a building must also keep the copies safe. A drawer of spare keys left on a café table defeats the purpose of every lock in the building. Tokens in a shared folder are spare keys on the café table.
Test accounts
Use dedicated test accounts with limited rights, never staff or customer accounts. Rotate their passwords after large campaigns and keep the credentials out of the plan file by supplying them through data files or properties that are not committed to shared repositories.
Sharing scripts
Recorded scripts often embed real addresses, cookie values and tokens from the recording session. Scrub them before the plan is shared, and remove any hard-coded tokens that were replaced by correlation but remain in disabled elements or comments.
Posting a screenshot of a debug view in a public forum while asking for help. Tokens and personal data in the image can outlive the question by years.
29Design Patterns for Maintainable Correlation
A few repeatable shapes keep correlated scripts understandable months later.
Capture next to the source
Attach each extractor to the sampler whose reply holds the value, and name it after the value, so cause and effect sit together.
One naming scheme
Use a consistent, descriptive naming style for variables, such as the purpose followed by the stage, so a reader can see what a variable holds.
Fail loudly
Give every capture a deliberately odd default and add an assertion on the first request that uses it, so a miss is reported at once.
Reusable fragments
Package a sign-in sequence, with all its captures, as a module that other scenarios include, so a fix is made in one place.
Verify with a single user first
Run one user with full tracing after every change to the captures, before scaling to many users.
Document the dynamic values
Keep a short list in the plan comments of each dynamic value, where it comes from and where it is used.
A well-run kitchen labels every container and keeps each ingredient next to the station that uses it. When a new cook arrives, nothing needs explaining. Good correlation reads the same way.
30Anti-Patterns to Avoid
These habits look harmless and cause the most painful failures.
Problem
A recorded token is left typed into a request because the test happened to pass once with it.
Why It’s Harmful
The test passes only while the old token remains valid, or because the server ignores it. When validation tightens, every user fails, and the cause is hard to see because the script looks complete.
Correct Approach
Search the plan for every value that appeared in the recording and differs between two recordings, and replace each with a variable fed by an extractor.
Problem
A failed capture is silently accepted because the default value is empty or looks plausible.
Why It’s Harmful
Later requests fail in confusing ways, and results show errors far from the real cause. Teams chase the server when the script is at fault.
Correct Approach
Use an obvious default and assert on the first dependent request so that the failure is stopped and named at the point where it happens.
Problem
A single extractor is placed at the thread-group level to catch everything, with a default value set.
Why It’s Harmful
Every response that lacks the value overwrites a good variable with the default, breaking later requests unpredictably.
Correct Approach
Attach extractors to the specific samplers that issue the value, and use broad scope only for values present in every response.
Problem
The same session is shared by every virtual user because a token was captured once in a setup step and placed in a global property.
Why It’s Harmful
The server sees thousands of requests from one logical user, which triggers throttling, hides per-user behaviour and does not represent real traffic.
Correct Approach
Capture the token inside each virtual user’s own flow, or use a pool of distinct accounts, each with its own capture.
Problem
Success is judged only by response codes, and the pages that came back are never checked for content.
Why It’s Harmful
Many applications return a success code with an error page. The test reports fast, healthy results while users would see failure.
Correct Approach
Add assertions on a phrase that only appears on a genuine success page, at key steps of the journey.
31Advantages, Costs and Trade-Offs
Correlation is necessary for realism, but it is not free.
| Benefit | Cost |
|---|---|
| Makes scripts replay on stateful applications at all | Takes analysis time for each dynamic value |
| Each virtual user behaves like a distinct real user | Adds extractors that need maintenance when pages change |
| Exposes real server behaviour such as session handling | Adds small processing cost per response on the generator |
| Fails fast when the application changes | Failures can look like server problems until diagnosed |
| Documents the dependencies between requests | Needs documentation habits to stay readable |
Think of insurance on a house. It takes a little effort and money each year, and the benefit seems invisible until the day it matters. A script without correlation is an uninsured house: fine until the first storm.
When the trade-off tilts
For a stateless public page that serves identical content to everyone, correlation may be unnecessary. For anything with sign-in, forms, carts or tokens, it is mandatory. The skill lies in correlating what must be correlated and leaving the rest alone, because every extra extractor is another piece to maintain.
Do not correlate values that do not change. A constant copied into a variable adds a moving part and no realism.
32Best-Practices Checklist
Run through these points before declaring any correlated script ready.
Record twice and compare
Every difference between recordings is a candidate dynamic value; decide for each whether it needs capture or parameterisation.
Pick the simplest extractor
Structured replies get structured extractors; text snippets get boundaries; patterns are for what boundaries cannot express.
Anchor on stable neighbours
Anchor on field names and keys, not on position or surrounding styling.
Set a loud default
Use an obvious placeholder default and an assertion that catches it.
Handle rotation and expiry
Recapture values that change per response and refresh values that expire.
Check the encoding
Make sure special characters are neither lost nor encoded twice.
Validate with one user, then a few, then many
Increase concurrency in steps so each stage exposes its own class of problem.
Turn off debug aids for the measured run
Remove result trees and debug elements, and keep only the result file with failure details.
33Real-World Scenarios
Four familiar situations show how the pieces combine.
Online shop with a cart
Browse a category, capture the identifier of a randomly chosen product from the listing, add it to the cart, capture the cart identifier and the anti-forgery token from the cart page, then check out. Each step uses a value from the step before, and a random choice keeps users from all buying the same item.
Corporate portal with single sign-in
Follow the redirect chain, capture the state, the hidden form fields and the returned code, and extract the access token from the exchange. Place the sign-in under a Once Only Controller so each user signs in once and then repeats business pages.
Classic form application with hidden state
Every page carries hidden view-state and validation fields. The CSS selector extractor reads each from the page that issued it, and an extractor follows every form submission because the values change after each post.
Service API returning structured replies
Create a resource, read its identifier from the structured reply, then update and delete it by that identifier. Extract the token once and send it in a shared header manager. Assertions confirm each reply contains the expected status field.
Each scenario is a different recipe, yet they share the same technique: taste what the pan gave you, and season the next step with it. The ingredients vary; the method of passing flavour forward is constant.
34Frequently Asked Questions
Short answers to the points that most often trip up newcomers.
Do I always need correlation?
Only when the application issues values that must be echoed back and that differ between users or visits. Static sites often need none.
How do I know which values are dynamic?
Record the same journey twice, with different accounts if possible, and compare. Anything that differs, other than the data you typed, is a suspect.
What is the difference between correlation and parameterisation?
Parameterisation feeds your own varied data into requests. Correlation reads values the server generated and returns them to the server.
Which extractor should I start with?
Use the one that matches the shape of the reply: JSON for structured data, selector for page elements, boundary for simple text, pattern when the others cannot express the rule.
Why does my variable show the default value?
The extractor did not match. Compare the raw response in the viewer with your boundaries or pattern, check which part of the response is being searched and confirm that the extractor is attached to the correct request.
Why does a correct-looking token get rejected?
Common causes are encoding problems, an older generation of the token, an expired token, or a missing cookie that ties the token to the session.
Should I keep the first match or the last?
Choose according to the page. If the value you need is the first of its kind, use match one; if values repeat and the last is current, use the last or capture all and choose.
Can one extractor capture several things?
Yes. A pattern with several groups and a template can capture or combine multiple pieces, though separate extractors are usually easier to read.
Do cookies need correlation?
Generally no. The cookie manager stores and replays cookies automatically, provided it is present and its clearing behaviour matches the scenario.
How do I handle values that appear in headers?
Point the extractor at the response headers instead of the body, and read the address or token from the relevant header line.
What if the value is created by browser code rather than the server?
The test tool does not run page scripts, so you must reproduce the calculation with a function or script, or capture the inputs and compute the value yourself.
Why does it work for one user but fail for many?
Usually a value is hard-coded or shared among users, or the server rejects repeated use of one account. Search for typed-in identifiers and use distinct accounts.
How many extractors is too many?
There is no fixed number. Add one for each value that truly changes, and no more. If a script is full of extractors, check that each is justified by the two-recording comparison.
Is there a tool that does this automatically?
Some recording tools and plugins suggest candidates by comparing recordings. Treat suggestions as hints, and always confirm them by inspecting the responses yourself.
35Summary and Key Takeaways
Correlation turns a brittle recording into a script that behaves like many real, distinct users.
Key Takeaways
- Correlation is capture and reuse. Read the fresh value the server issued, hold it in a variable for that user, and place it in the requests that need it.
- Find dynamic values by comparison. Two recordings, side by side, reveal every value that changes and therefore every value that needs attention.
- Match the extractor to the reply. Structured replies call for structured extractors; plain text calls for boundaries; patterns remain the flexible fallback.
- Anchor on what is stable. Field names and keys survive page redesigns; positions and styling do not.
- Make failures loud. An obvious default and a meaningful assertion stop a missed capture at its source, not nine requests later.
- Remember rotation, expiry and encoding. Recapture values that change, refresh values that expire, and check that special characters travel intact.
- Verify before scaling. One user with full tracing first, then a few, then many, and a quiet command-line run with debug aids switched off for the real measurement.