Session Signals

Read the signals Steel records on each session, such as CAPTCHAs, bot blocks, and proxy failures, and find the sessions that hit them.

Overview

Signals are labels that Steel adds to a session when it sees certain events during the run, such as a CAPTCHA or a bot block. You don't set signals. To attach your own labels, use session metadata.

type: info Session signals need steel-sdk 0.21.0 or later, in TypeScript and Python.

1
import Steel from 'steel-sdk';
2
3
const client = new Steel();
4
5
const session = await client.sessions.retrieve(sessionId);
6
7
console.log(session.signals);

signals is an array of signal names. Sessions in sessions.list results carry the same field:

JSON
1
["captcha_encountered", "bot_detection_triggered"]

Available Signals

SignalWhat it means
captcha_encounteredA CAPTCHA was detected during the session.
bot_detection_triggeredA page ended on an anti-bot block or challenge that the browser did not get past.
proxy_connection_failedThe proxy connection failed or was unreliable.
session_timeout_exceededThe session ended on its timeout or inactivity limit.
context_restoredThe session restored a previously saved browser context.

For the exact reason a session ended, read its releaseReason. See Why a Session Ended.

When Signals Appear

Steel adds signals to a session when the session ends. While the session runs, signals is an empty array. Steel fills it in within a few seconds after release.

1
await client.sessions.release(session.id);
2
3
await new Promise((resolve) => setTimeout(resolve, 10_000));
4
5
const { signals } = await client.sessions.retrieve(session.id);

An empty array doesn't prove that nothing happened. Detection uses heuristics and doesn't cover every case. A signal records that Steel saw the event at some point in the session. It doesn't describe the final state of the page.

Look Up Signal Definitions

signalCatalog returns the current signals with a label and a description for each. Use it to show signals in your own UI without hardcoding the list.

1
const catalog = await client.sessions.signalCatalog();
2
3
for (const signal of catalog.signals) {
4
console.log(signal.value, signal.label, signal.severity);
5
}

Each entry has a severity of info, warning, danger, or success. The semantics field states the same limits as the section above:

JSON
1
{
2
"signals": [
3
{
4
"value": "bot_detection_triggered",
5
"label": "Bot blocked",
6
"description": "A page ended on an anti-bot block or challenge that the browser did not get past",
7
"source": "derived",
8
"severity": "warning"
9
}
10
],
11
"semantics": "Signals record what was observed at some point during a session, not the current page state. ..."
12
}

Steel can add signals over time. Handle signal values that you don't recognize.

Find Sessions by Signal

Pass signal to sessions.list to find sessions that carry a signal. If you pass several signals, a session must carry all of them. Combine signal with metadata to narrow the search to one of your jobs or customers.

1
for await (const session of client.sessions.list({
2
metadata: { job_id: 'job-1042' },
3
signal: ['bot_detection_triggered'],
4
})) {
5
console.log(session.id, session.signals);
6
}

Over HTTP, repeat the signal parameter for each signal:

cURL
1
curl -G https://api.steel.dev/v1/sessions \
2
-H "steel-api-key: $STEEL_API_KEY" \
3
--data-urlencode "signal=captcha_encountered" \
4
--data-urlencode "signal=bot_detection_triggered"
  • The list leaves out failed sessions unless you pass status or releaseReason. See Find Past Sessions.
  • The dashboard shows signals in the sessions list and on each session page.
Need help with session signals?

Reach out to us on the #help channel on Discord or @steeldotdev.