skip to content

In JMeter's HTTP(S) Test Script Recorder, how do the URL Patterns to Include and Exclude decide what is kept?

level: middleimportance: must knowfreq 62%

answer

  1. Two lists, evaluated in a fixed order
  2. The match string is not the full URL
  3. Whole-string matching, not a search
  4. An empty include list means no restriction

basics

~20 s

Both fields hold regular expressions matched against the whole host:port/path?query string. With any Include pattern present the URL must match one, and matching any Exclude pattern drops it. Filtering decides what is recorded, not what the browser receives.

solid answer

~40 s

The recorder builds a match string of `domain:port/path?query` — for `http://localhost/jmeter/index.html?username=xxxx` that is `localhost:80/jmeter/index.html?username=xxxx` — and tests it against both lists as Jakarta ORO regular expressions, using **whole-string** matching. So `\.html` matches nothing; you need `.*\.html(\?.*)?`. The rule is: if the Include list is non-empty the URL must match at least one entry, and then if the Exclude list is non-empty it must match none. Two empty lists record everything, which is why one page arrives as dozens of samplers. The **Add suggested Excludes** button fills the list from the `proxy.excludes.suggested` property, a case-insensitive pattern over common static extensions. A separate **Content-type filter** on the same panel is checked first, against the response content type. Filtered requests still reach the browser; they are only kept out of the tree.

code

text · 4 lines
text
(?i).*\.(bmp|css|js|gif|ico|jpe?g|png|swf|eot|otf|ttf|mp4|woff|woff2)
(?i).*\.(bmp|css|js|gif|ico|jpe?g|png|swf|eot|otf|ttf|mp4|woff|woff2)[\?;].*
.*detectportal\.firefox\.com.*
www\.google-analytics\.com.*

go deeper

for a junior

Know that the recorder has two filter lists and that leaving both empty records every image, stylesheet and beacon the browser fetched. Recognising why a recording has 300 samplers is the entry-level point.

for a middle

Explain the match string the patterns are tested against, that matching is whole-string rather than a search, and the include-then-exclude order. Be able to say why a bare fragment pattern matches nothing.

for a senior

Diagnose a filter that is eating the wrong traffic: watch the bracketed labels in a View Results Tree under the recorder, check jmeter.log for skipped invalid patterns, and remember filters only reload on Restart.

for a principal

Own the exclude list as a shared artefact rather than a personal habit. Recordings that arrive pruned differently are not comparable, and comparability is what makes a re-record cheap to review.

Filtering is the difference between a recording you can work with and a recording that is 300 samplers of fonts, sprites and analytics beacons. JMeter gives you two independent filters on the recorder's **Requests Filtering** panel, and they behave differently enough that mixing them up is the usual cause of "why did nothing record". ## What the pattern is matched against The recorder does not match against the URL you typed. It builds a string from the generated sampler's **domain, port, path and query**, joined as `domain:port/path` plus `?query` when there is one. The manual's own example: browsing `http://localhost/jmeter/index.html?username=xxxx` produces the match string ``` localhost:80/jmeter/index.html?username=xxxx ``` Note that the scheme is gone and the port is always present, filled in from the implied default when the URL did not carry one. The patterns are Jakarta ORO regular expressions, and the match is a **whole-string** match, not a search. This is the single most common trap: `\.gif` matches nothing at all, because the whole string has to be consumed. You want `.*\.gif` or `.*\.gif(\?.*)?`. A pattern that does not compile is skipped with a warning in `jmeter.log` rather than failing the recorder, so a typo shows up as "my filter does nothing". ## The two-stage rule Both lists are evaluated for every request, in this order: 1. **Include** — if the list is empty, everything passes this stage. If it has at least one entry, the URL must match **at least one** of them or it is not recorded. 2. **Exclude** — if the list is empty, everything passes. If it has entries, a URL that matches **any** of them is not recorded. So exclude wins over include, and the two are useful for different jobs: an include list of `.*\.jsp` or `.*/api/.*` says "only my application", while an exclude list says "everything except this noise". Most real recordings use both — include the hosts you own, exclude the assets on them. ## Content-type filter Just above the URL patterns sits a **Content-type filter** with its own Include and Exclude boxes. These are checked against the *response's* content type (`text/html`, `image/png`) rather than the request URL, and they are applied **before** the URL filter — a sample has to pass the content-type check and then the URL check to be recorded. Because it inspects the response, it catches things a URL pattern cannot: an extensionless endpoint that returns an image, for instance. The `proxy.content_type_include` and `proxy.content_type_exclude` properties seed the two fields. ## What "filtered out" actually means A filtered request is still proxied. The browser gets its response exactly as it would have; only the *recording* is suppressed. Two visible consequences: - the filtered sample's label is wrapped in square brackets, so a View Results Tree under the recorder shows entries such as `[23 /favicon.ico]`; - whether child listeners see those entries at all is governed by the **Notify Child Listeners of filtered samplers** checkbox, which is on by default and which the bundled Recording template turns off. That is a useful pair when you are debugging a filter: turn notification on, watch the bracketed labels go by, and you can see precisely which pattern is eating a request you wanted. ## Getting a sane starting list The **Add suggested Excludes** button under the exclude table appends a ready-made list drawn from the `proxy.excludes.suggested` property. Its built-in default is one case-insensitive alternation over `bmp|css|js|gif|ico|jpe?g|png|swf|woff|woff2`; several entries can be shipped by separating them with `;`. The bundled Recording template goes further, adding rows for browser chatter such as `detectportal.firefox.com`, safebrowsing endpoints and toolbar update hosts — traffic your browser generates that has nothing to do with the application. ## Operating notes - Edit a pattern while the proxy is running and it has no effect until you press **Restart**; the filters are read when the proxy starts. - Filtering out assets during recording is not the same as never requesting them at replay. If you want the load to include them, record only the page requests and let the sampler fetch embedded resources instead — that flag belongs to the HTTP Request sampler (`dev-jmeter-protocols-http-sampler`). - Filtering is per-recorder, so two recorders in one plan can hold different lists.

  • You added an include pattern and now nothing records at all. What do you check first?
    That the pattern matches the whole `domain:port/path?query` string. `.*\.jsp` matches, `\.jsp` does not, and neither does a pattern written against the full URL with its scheme. Then check `jmeter.log` for a skipped-invalid-pattern warning, and press Restart — filter edits are only picked up when the proxy restarts.
  • How does the Content-type filter differ from the URL patterns?
    It is matched against the response's content type instead of the request URL, and it is applied first. That lets it catch a sample whose URL gives nothing away — an endpoint with no extension that returns an image, for example — at the cost of only being decidable once the response has come back.

saying these in an interview costs you the question

  • Writes \.gif and expects it to match a URL ending in .gif
  • Thinks an exclude pattern stops the browser from loading the asset
  • Believes the pattern is matched against the full URL including https://
  • Assumes an empty Include list means nothing is recorded
  • Expects a pattern edit to take effect without restarting the proxy