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.
1import Steel from 'steel-sdk';23const client = new Steel();45const session = await client.sessions.retrieve(sessionId);67console.log(session.signals);
signals is an array of signal names. Sessions in sessions.list results carry the same field:
1["captcha_encountered", "bot_detection_triggered"]
Available Signals
| Signal | What it means |
|---|---|
captcha_encountered | A CAPTCHA was detected during the session. |
bot_detection_triggered | A page ended on an anti-bot block or challenge that the browser did not get past. |
proxy_connection_failed | The proxy connection failed or was unreliable. |
session_timeout_exceeded | The session ended on its timeout or inactivity limit. |
context_restored | The 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.
1await client.sessions.release(session.id);23await new Promise((resolve) => setTimeout(resolve, 10_000));45const { 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.
1const catalog = await client.sessions.signalCatalog();23for (const signal of catalog.signals) {4console.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:
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.
1for await (const session of client.sessions.list({2metadata: { job_id: 'job-1042' },3signal: ['bot_detection_triggered'],4})) {5console.log(session.id, session.signals);6}
Over HTTP, repeat the signal parameter for each signal:
1curl -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
statusorreleaseReason. See Find Past Sessions. - The dashboard shows signals in the sessions list and on each session page.
Reach out to us on the #help channel on Discord or @steeldotdev.