Pre-Processors run before a sampler executes. Post-Processors run after. Think of them like "before" and "after" hooks in test automation frameworks. Pre-Processors set up the request (generate dynamic data, modify parameters). Post-Processors extract data from the response (session tokens, IDs, correlation values) for use in subsequent requests. This is where correlation happens -- the single most important skill in performance testing scripting.
The JSON Extractor is the post-processor you will use most often. It extracts values from JSON responses using JSONPath expressions and stores them in JMeter variables. The classic use case: login returns a token, you extract it, and use it in all subsequent requests.
# Add: Right-click HTTP Request → Post Processors → JSON Extractor
# API Response:
# {
# "token": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiam9obiJ9.abc123",
# "user": {
# "id": 42,
# "name": "John Doe",
# "roles": ["admin", "user"]
# },
# "products": [
# { "id": 101, "name": "Widget", "price": 9.99 },
# { "id": 102, "name": "Gadget", "price": 19.99 }
# ]
# }
# Extract the auth token:
Variable Names: authToken
JSON Path: $.token
Match No: 1
Default Values: TOKEN_NOT_FOUND
# Extract user ID:
Variable Names: userId
JSON Path: $.user.id
Match No: 1
Default Values: -1
# Extract first product ID:
Variable Names: productId
JSON Path: $.products[0].id
Match No: 1
Default Values: -1
# Extract ALL product IDs (comma-separated):
Variable Names: allProductIds
JSON Path: $.products[*].id
Match No: -1
Default Values: NONE
# Result: allProductIds_1 = 101, allProductIds_2 = 102, allProductIds_matchNr = 2
# Use in next request:
# Header: Authorization = Bearer ${authToken}
# URL: /api/users/${userId}/orders
# Body: { "productId": ${productId} }When the response is HTML (CSRF tokens, session IDs in hidden fields) or a non-JSON format, the Regular Expression Extractor is your tool. It uses Java regex to find and capture values. The key concept is the capturing group: the part in parentheses () is what gets extracted.
# Add: Right-click HTTP Request → Post Processors → Regular Expression Extractor
# Example 1: Extract CSRF token from HTML
# HTML: <input type="hidden" name="csrf_token" value="abc123def456">
Field to Check: Response Body
Variable Name: csrfToken
Regular Expression: name="csrf_token" value="(.+?)"
Template: $1$
Match No: 1
Default Value: CSRF_NOT_FOUND
# Example 2: Extract session ID from Set-Cookie header
# Header: Set-Cookie: JSESSIONID=A1B2C3D4E5F6; Path=/; HttpOnly
Field to Check: Response Headers
Variable Name: sessionId
Regular Expression: JSESSIONID=([^;]+)
Template: $1$
Match No: 1
Default Value: SESSION_NOT_FOUND
# Example 3: Extract multiple values
# URL in response: /orders/12345/items/67890
Variable Name: orderId
Regular Expression: /orders/(\d+)/items/(\d+)
Template: $1$ ← gets orderId (12345)
# For itemId, use: $2$ ← gets itemId (67890)
# Template syntax:
# $0$ = entire match
# $1$ = first capturing group (first set of parentheses)
# $2$ = second capturing group
# $1$$2$ = concatenate group 1 and group 2If you are extracting values from HTML responses and regex feels fragile, the CSS/JQuery Extractor uses CSS selectors (just like jQuery) to find elements. It is more readable and more resilient to minor HTML changes.
# Add: Right-click HTTP Request → Post Processors → CSS/JQuery Extractor
# Example: Extract CSRF token from HTML
# <input type="hidden" name="csrf_token" value="abc123def456">
CSS/JQuery expression: input[name=csrf_token]
Attribute: value
Variable Name: csrfToken
Match No: 1
# Example: Extract all product links
# <a class="product-link" href="/products/42">Widget</a>
CSS/JQuery expression: a.product-link
Attribute: href
Variable Name: productLink
Match No: 0 (0 = random match)
# Example: Extract text content of a heading
# <h1 class="page-title">Welcome, John</h1>
CSS/JQuery expression: h1.page-title
Attribute: (empty -- gets text content)
Variable Name: pageTitle
Match No: 1The JSR223 Pre-Processor runs Groovy code before the sampler executes. Use it when you need to generate dynamic data that JMeter functions cannot handle -- timestamps in specific formats, cryptographic signatures, complex business logic for request parameters.
// Example 1: Generate ISO timestamp for API request
import java.time.Instant
import java.time.format.DateTimeFormatter
def timestamp = Instant.now().toString()
vars.put("requestTimestamp", timestamp)
// Use in request body: { "timestamp": "${requestTimestamp}" }
// Example 2: Generate HMAC signature for authenticated API
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import java.util.Base64
def secret = vars.get("apiSecret")
def message = vars.get("requestBody")
def mac = Mac.getInstance("HmacSHA256")
mac.init(new SecretKeySpec(secret.bytes, "HmacSHA256"))
def signature = Base64.encoder.encodeToString(mac.doFinal(message.bytes))
vars.put("hmacSignature", signature)
// Use in header: X-Signature: ${hmacSignature}
// Example 3: Generate unique order reference
def threadNum = ctx.getThreadNum()
def iteration = vars.getIteration()
def orderRef = "ORD-${threadNum}-${iteration}-${System.currentTimeMillis()}"
vars.put("orderRef", orderRef)
// Result: ORD-5-3-1701234567890// Example: Extract and transform data from complex JSON response
import groovy.json.JsonSlurper
def response = prev.getResponseDataAsString()
def json = new JsonSlurper().parseText(response)
// Extract and store multiple values
vars.put("totalItems", json.pagination.total.toString())
vars.put("currentPage", json.pagination.page.toString())
// Pick a random product from the list
def products = json.products
if (products && products.size() > 0) {
def randomIndex = new Random().nextInt(products.size())
def product = products[randomIndex]
vars.put("randomProductId", product.id.toString())
vars.put("randomProductName", product.name)
vars.put("randomProductPrice", product.price.toString())
log.info("Selected product: ${product.name} (ID: ${product.id})")
} else {
vars.put("randomProductId", "NOT_FOUND")
log.warn("No products found in response")
}
// Store response time for custom reporting
def responseTime = prev.getTime()
if (responseTime > 2000) {
log.warn("SLOW REQUEST: ${prev.getSampleLabel()} took ${responseTime}ms")
}Use the built-in extractors (JSON, RegEx, CSS) whenever possible. They are faster and more memory-efficient than JSR223 scripts. Use JSR223 only when you need complex logic -- random selection, calculations, data transformation, or cryptographic operations that built-in extractors cannot handle.
| Extractor | Best For | Syntax Example | Performance |
|---|---|---|---|
| JSON Extractor | REST API JSON responses | $.user.token | Fast |
| Regular Expression | HTML, headers, any text format | token="(.+?)" | Fast |
| CSS/JQuery | HTML with complex structure | input[name=csrf] | Medium |
| XPath Extractor | XML and SOAP responses | //user/id/text() | Slow (XML parsing) |
| JSR223 (Groovy) | Complex logic, multiple extractions | Custom code | Varies (be careful) |
| Boundary Extractor | Simple text between markers | Left: "id": Right: , | Fastest |
Q: How do you handle dynamic values like session tokens or CSRF tokens in JMeter tests?
A: I use correlation -- extracting dynamic values from one response and passing them to subsequent requests. For JSON APIs, I use the JSON Extractor with JSONPath: after a login request, I extract the auth token using $.token and store it in a variable called authToken. Then I add an HTTP Header Manager with Authorization: Bearer ${authToken} for all subsequent requests. For HTML applications, I use the Regular Expression Extractor to capture CSRF tokens from hidden form fields, or the CSS/JQuery Extractor for cleaner syntax. The key is identifying which values are dynamic by comparing two recordings -- any value that changes between recordings needs correlation. I also set meaningful default values (like TOKEN_NOT_FOUND) so I can easily spot extraction failures in the results.
Key Point: Pre-Processors prepare requests (generate data). Post-Processors extract from responses (correlation). JSON Extractor for APIs, RegEx for HTML/headers, CSS/JQuery for structured HTML, JSR223 for complex logic. Correlation is the #1 scripting skill.
Key Point: Pre-Processors set up requests, Post-Processors extract data. JSON Extractor for APIs, RegEx for HTML. Correlation (extracting dynamic values) is the most critical scripting skill.