Session replay

DevTools in session replays

DevTools shows the console, network requests and page performance behind a session replay. Use it to find broken sessions in the Sessions list.

On this page

What it is for

A typical question: a trial user clicked "Pay" three times and left. Did the payment call fail, or did nothing happen?

What it needs

Platform What it needs
Websites Sequential's recorder on the page, from Session replay (web) or started by the Sequential SDK. It works with any analytics SDK.
Mobile apps A PostHog iOS or Android SDK that sends to Sequential. See Mobile apps.

Open DevTools in a replay

  1. In a replay, click </> DevTools in the header, or press D. The DevTools drawer opens.
  2. Pick the Console, Network or Performance tab.
  3. To move the replay to the moment before an entry, click the entry in the drawer.

If Sequential is still processing the recording, each tab says "DevTools data appears once the recording is ready (by 14:05).", with the time when it is ready. After the replay period, each tab says "This recording has expired."

Find the sessions that broke

  1. Open Sessions → Latest. The Problems column names the problems of each session, one badge per kind. For example: "2 JS errors", "1 failed request". Without DevTools counts, for example in a session with no recording, the badges count the session's error events and the problems stored from its recording, in your date range.
  2. To show only the sessions that broke, click With JS errors or With failed requests above the table.
  3. To turn a filter off, click it again.

A +, as in "12+ JS errors", means that the recorder reached a per-page limit. Some entries were not recorded. Read the number as "at least 12".

Turn captures on or off

Only owners and admins can change these settings.

  1. Go to Settings → Projects → your project → Session replay.
  2. In the DevTools group, tick or untick the captures and the console levels.
  3. To keep the values of some query parameters, add their names to Keep query values for.
  4. To skip some requests, add URL patterns to Don't record requests to. A pattern must match the whole URL.
  5. Click Save. If the change records more than before, the Loosen masking? sheet asks you to type the project slug.

If a pattern matches nothing, Sequential gives no warning. Those requests are still recorded.

  • The Web, iOS and Android tabs share one DevTools group. A change on one tab changes all platforms.

Mobile apps

DevTools shows only what PostHog's mobile SDKs send.

  • Console and Network only. Mobile sessions never match With JS errors.
  • No logs with the default settings. Sequential asks for logs only when Console has a level ticked and Record message text is on.
  • Failed requests can be higher than the count. Sequential cannot see a request that got no response, such as a timeout, and no setting changes that. So a mobile session with no observed failure does not match With failed requests.
  • An empty tab is ambiguous. Either the SDK sent nothing, or the capture was off.
  • Flutter apps send no logs and no requests. React Native sends requests on iOS only. iOS logs need captureLogs: true. Android requests need PostHogOkHttpInterceptor.

Limits

Per-page limit What the recorder does
1 MB of DevTools data Stops DevTools capture
1,000 requests Stops network capture
An entry over 64 KB Leaves out that entry
A burst of console messages or exceptions Rate-limits them

Each limit shows as a recorder notice in the Console tab and adds a + to the badge.

  • The Problems badges and the filters are not on Watch or Ask.
  • The list and the replay header count differently.
  • There is no badge or filter for console errors and warnings.
  • The Insights tab does not see these counts. So for a session that broke, its answer can differ from Watch. See Session insights.
  • When you turn a capture on, Sequential does not fill in older sessions.
  • The Sessions list does not count errors that your analytics SDK reports, such as PostHog exceptions. With JS errors does not find them.
  • Aborted requests, requests that the browser cancelled because the user left the page, prefetches, and failed images or scripts do not count as failed requests.
  • Performance measures full page loads only. It does not measure navigations inside a single-page app.
More questions DevTools answers
  • Which sessions this week had a JS error? You can watch the ones that broke, not a random sample.
  • A customer says the dashboard is slow. Did the main content paint in 1 second or in 6?
How Sequential stores and counts

On websites, Sequential's recorder captures JS errors, console output, network requests and page performance with each recording. Each is a capture that you turn on or off per project. All four are on by default.

  • Sequential stores only what the settings allow. When a recording arrives, Sequential applies the project's current DevTools settings, whatever the page sent.
  • Sequential counts only what it stored. It counts the JS errors and failed requests in the stored data. So the Sessions list never counts something that the replay cannot show you.
  • Errors that your analytics SDK reports itself also show in the DevTools drawer. An example is a PostHog exception event. The drawer marks these via PostHog. The Sessions list does not count them.
Other ways to open the drawer

If the session had problems, the badge on the </> DevTools button shows them. For example: "2 exceptions" or "1 failed".

If you click a JS error or a failed request on the timeline, the drawer opens on that entry. A link that you copy with Share opens the drawer again on the same tab. For what each tab shows, see Each tab in detail, below.

What the chips and filters count

What the badges count:

  • JS errors are uncaught exceptions and unhandled promise rejections that Sequential's recorder caught. They also include errors reported through the Smartlook compatibility script. See Moving from Smartlook.
  • console.error calls are not in this count. The drawer counts them separately.
  • A failed request is a fetch or XHR call that returned HTTP 400 or above. On websites, a call that ended in a network error or a timeout has also failed, also when the tab was in the background.
  • A call that the browser cancelled because the user left the page has not failed. Neither has a prefetch, which is a request that the page sends before the user needs it. This applies to sessions recorded from 13 October 2026. Before that day, the recorder could not tell a cancel when the user left the page from a network error.
  • To see the definitions, hover over the Problems cell. They show when the DevTools counts found a problem.

How the filters work:

  • If both filters are on, a session must match both.
  • Latest loads 100 sessions at a time. Sequential applies the filter before it splits the list into pages. So the filter finds broken sessions anywhere in the date range.
The three states of a session

A badge names problems only. For each kind of problem, a session is in one of three states. Two of them show no DevTools badge.

State What it means On the row
Counted Sequential checked the session for that kind of problem. A badge if it found any. No badge if it found none.
Not captured Sequential counted the session, but not this kind. The recording or the app's SDK did not report it. No DevTools badge. The row leaves the kind out. It never shows it as 0 or "off".
Not measured Sequential has not counted all of the session. No DevTools badge.

The difference is important when a filter is on. The list shows a note with the number of recorded sessions in the date range that it could not check. These notes ignore your other filters:

  • "N sessions in this range weren't checked for DevTools signals." These sessions are not measured.
  • "N sessions in this range couldn't be checked for this filter (that capture was off, or wasn't reported)." These sessions are not captured.
Why a session is not captured or not measured

Not captured

  • On websites, the recording did not report that kind. Usually that capture was off for your project.
  • A website recording with no DevTools data at all is also in this state once Sequential counts it. An example is a recording made before DevTools existed.
  • On mobile, your app's SDK did not report that kind.
  • A mobile session with no observed failed request is also in this state. Sequential cannot see a request that got no response.

Not measured

  • Sequential has no counts for the session. Sequential counts each part of a recording when the part arrives, so this does not happen to a recording that the current server stored.
Why Sequential does not show zero

A zero reads as "nothing went wrong". If unchecked sessions counted as zero, With JS errors would silently drop every older broken session. The list would then call those sessions clean.

The AI judge behind Watch and Ask reads these counts too. Sequential never tells the judge zero for something it did not count.

If Sequential counted only part of a session and N is above zero, it tells the judge "at least N". So Watch can rank a session for its errors while its row on Latest shows no badge.

What each capture records
Capture What it records What it never records Default
JavaScript errors Uncaught exceptions and unhandled promise rejections, with their message and stack trace — On. Web only
Console For each ticked level: each call's level, how often it happened and where. A stack trace for warnings and errors Message text, unless Record message text is on On for Errors, Warnings, Info and Logs. Debug off. Text off
Network requests Method, URL, status, timing and size. Under Strict, the URL is shorter (see How masking changes DevTools addresses) Headers and bodies. Query values, except for keys under Keep query values for. Requests that match Don't record requests to On, keeping no query values
Performance Core Web Vitals and page-load timing, once per page load — On. Web only

Whatever the settings, Sequential replaces some values with [redacted] in DevTools data. This redaction catches only known formats. It is not a guarantee. See What Sequential redacts, below, and Masking and redaction.

Each tab in detail

Console

  • Each row shows the time, the level, the message and where the app logged it, such as cart.js:42.
  • To filter, use the level chips Errors, Warnings, Info, Logs and Debug.
  • To search, use Filter console.
  • To see a row's kind, full text, arguments and stack trace, click the row.
  • On an exception or an error-level row, the detail has Ask your agent. It hands a prompt about that error to a coding agent on your computer. See Find and replay sessions.

The kinds are:

  • Uncaught exception
  • Unhandled promise rejection
  • Custom error, for an error sent through the Smartlook compatibility script
  • a console call
  • Reported by PostHog

If an error reads only Script error., the browser hid its details, because the script comes from another origin. To see the details, add crossorigin="anonymous" to the script tag. Then serve the script with CORS headers.

Network

Each row is one request, with Method, Status, Name, Type, Size and Duration. A status can be, for example, "404 Not Found" or "Timed out". On websites, these statuses are also possible:

  • "Cancelled (page left)": the browser cancelled the request because the user left the page. This is not a failure.

  • "Failed (background tab)": the request failed while the tab was in the background. This is a failure.

  • A prefetch has "(prefetch)" after its name. A prefetch is never a failure.

  • Failed only shows only the failed requests.

  • The type selector shows one type, such as Fetch/XHR or Document.

  • Filter requests searches the URLs. Under Strict, the path of a file that the page loads is masked, so you cannot search for its file name.

  • In the detail of a request, a query value that Sequential did not keep reads "value not recorded".

Aborted requests, requests cancelled because the user left the page, prefetches, and failed assets, such as images and scripts, do not count as failed requests.

Performance

  • The tab shows one card per full page load.
  • It does not measure navigations inside a single-page app separately.
  • Each card shows the Core Web Vitals LCP, INP, CLS, FCP and TTFB. Each is rated Good, Needs work or Poor.
  • To see the cut-offs, hover over the name of a vital.
  • A vital that the page never reported reads Not reported.
  • Below the vitals, a bar splits the load into DNS, Connect, Request, Response, DOM and Load.
What Sequential redacts

Whatever the settings, Sequential replaces these values with [redacted] in DevTools data:

  • JWTs, and Bearer and Basic credentials
  • email addresses
  • card numbers that pass a Luhn check
  • values logged under key names such as token, password or secret

On websites, Sequential does this before anything leaves the browser, and again on the server. See Masking and redaction.

How masking changes DevTools addresses

The Attribute text masking setting also changes the addresses in DevTools. Strict uses Strict. Balanced uses Off. The recorder applies the rule in the browser, and Sequential's servers apply it again under the project's current setting.

What Strict URLs (Custom) Off (Balanced)
A network request for a file that the page loads, such as an image, CSS, a script, a font or media Domain kept. Every path segment masked. No query Path kept. No ; parameters. Query values [redacted] Path kept. Query values [redacted]
A fetch or XHR call, and the page itself Domain and route kept. Id-like segments masked. No ; parameters. Query values [redacted] Path kept. No ; parameters. Query values [redacted] Path kept. Query values [redacted]
Code locations: the file of an error, each stack frame, and where a console entry came from A script or other asset file: domain kept, every path segment masked, no query. Any other address: domain and route kept, id-like segments masked, query values [redacted]. Line and column kept Path kept. No ; parameters. Query values [redacted] Path kept. Query values [redacted]
http(s) and ws(s) addresses in error messages and console text Changed as code locations are Changed as code locations are Kept. Only redaction runs
UUIDs, hex runs of 16 or more characters and runs of 6 or more digits after a / in error messages, console text and stack frames Masked Kept Kept
  • A request with no kind, or a kind that Sequential does not know, counts as a file.
  • Keep query values for applies to network requests only. In every setting, query parameter names stay, and addresses lose the #fragment and any user:pass@.
  • Under Strict and URLs, a query item with no =, such as ?<uuid>, becomes [redacted].
  • A segment is id-like when it holds a UUID, a hex run of 16 or more characters or an email address anywhere, such as <uuid>.json. Masking and redaction gives the full rule.
  • The text rule reads each word that holds a /, and masks only what comes after the first /. Prose such as and/or, 2026/09/29 and v1/2 stays as it is.

What Strict does not mask in DevTools:

  • Domain names, and query parameter names.
  • Numbers of 5 digits or fewer, and name slugs, in the route of an API call.
  • An id in text with no / before it in its word, such as id=<uuid>. The keys of a logged object.

Under Strict, you cannot see which file failed to load. A failed image, script or font shows only its domain, its kind, its status and its timing. To find the file, reproduce the issue in a browser, or use Attribute text set to URLs on a staging project.

Console message text in detail

While text is off, console rows read like console.log at cart.js:42. With text on, you also see the words that your app logged, such as "payment failed: card_declined". This is the difference between knowing that console.error fired and knowing why.

Exceptions keep their message either way. There is one case where this is not true: a promise rejected with a plain object, not an Error or a string. While text is off, that rejection reads only as its type, such as Unhandled rejection: [object Object].

Redaction catches formats, not meaning. For example, Sequential does not redact console.log("reset link for", user, "is", url). It also does not redact names, addresses, one-time links, custom tokens or logged API responses.

  • Turn text on freely in a staging or development project.
  • In production, turn it on only after you check what your app logs.
  • Settings are per project. So you can turn text on in a staging project and keep it off in a production project.

While text is off, Sequential empties message text as it arrives. This includes text from an older recorder, or from a mobile SDK that sends it. Text that is already stored stays in the recording. Sequential cannot remove it. See Retention and deletion.

Settings in detail
  • Other roles see the form read-only, with "Ask an owner or admin to change this."
  • In the DevTools group, the settings are JavaScript errors, Console and its levels, Record message text, Network requests and Performance.
  • The DevTools group is one setting, shared by the Web, iOS and Android tabs.
  • On the mobile tabs, JavaScript errors and Performance are greyed out and marked "Web only."
  • A pattern matches the whole URL, scheme and host included, but not the query. So write https://api.example.com/health or **/health, not /health.
  • In a pattern, * stays within a path segment. ** crosses path segments.
  • These changes record more than before, so they open the Loosen masking? sheet:
    • errors, console or network capture turned on
    • a level added
    • message text turned on
    • a query value kept
    • a request pattern removed

Sequential applies your current settings to every upload as it arrives. So when you turn a capture off, Sequential stops storing that data immediately. Websites use the change on their next page load. Mobile apps use it on their next launch. See Recording settings.

Mobile apps in detail

iOS and Android recordings come from PostHog's mobile SDKs. See Mobile apps.

  • The Performance tab reads "Performance metrics are recorded for websites."
  • Every mobile log counts as console output, never as an exception. So mobile sessions never match With JS errors. With that filter on, the list counts them in its notes.
  • On mobile, a request counts as failed only when it returned HTTP 400 or above. Sequential cannot see a request that got no response, such as a timeout or no connection. No setting changes that.
  • So a mobile session with no observed failure does not match With failed requests, and the real number of failed requests can be higher than the count.
  • The replay cannot tell an SDK that sent nothing from a capture that was off. The empty tab says this.
Per-SDK differences on mobile

Logs

  • Native iOS apps must also set captureLogs: true.
  • Android sends logcat by default.
  • In React Native, captureLog is on by default.
  • The Flutter SDK does not send logs.

Network requests

  • iOS sends requests from URLSession by default.
  • Android needs PostHogOkHttpInterceptor.
  • React Native sends requests on iOS only.
  • Flutter sends none.

Requests with no response

Mobile SDKs send request metrics only. Sequential cannot see a request that got no response at all, such as a timeout or no connection. PostHog's mobile SDKs do not report it, and no setting changes that.

So a mobile session with no observed failure is "couldn't be checked", never "0 failed requests". It shows no badge for it. It does not match With failed requests. The list counts it in its note.

Why the list and the header counts differ
  • The list counts every occurrence of an error that Sequential's recorder caught.
  • The header counts each drawer row once. This includes errors that PostHog reported.
  • An error that repeats quickly is one drawer row, marked ×N.

So a header's "3 exceptions" can show beside a row's "2 JS errors". Or "1 exception", one row marked ×5, can show beside "5 JS errors".

Why Insights can differ from Watch

The Insights tab judges the session from its events. It does not see the DevTools counts. So for a session that broke, its answer can differ from the answer in Watch. See Session insights.