Variables & BotData
BotData is the shared state object for a single bot execution. Every variable produced by a block lives in BotData and is accessible by all subsequent blocks via <varName> syntax.
BotData Overview
Each bot run has its own BotData instance, isolated from other bots running concurrently. BotData holds:
- All variables (automatic and user-defined)
- The current bot status (
NONE,SUCCESS,FAILURE, etc.) - Cookie jar and session objects for HTTP, IMAP, POP3, SMTP, FTP
- The log for the current run
Variables in BotData persist for the entire script run and are cleared when the bot finishes.
Automatic Variables
These variables are set automatically after certain blocks execute. They are always available in Keycheck and Parse combo-boxes.
| Variable | Set by | Content |
|---|---|---|
| <SOURCE> | HTTP Request, TLS Request, Navigate (Selenium) | Response body decoded as UTF-8 text. For Selenium, this is the page HTML. |
| <RESPONSECODE> | HTTP Request, TLS Request | HTTP status code as a string, e.g. "200", "403". |
| <ADDRESS> | HTTP Request, TLS Request, Navigate | Final URL after all redirects. For Selenium, the current page URL. |
| <HEADERS(*)> | HTTP Request, TLS Request | All response headers concatenated as a single string. |
| <HEADERS{name}> | HTTP Request, TLS Request | A specific response header by name, e.g. <HEADERS{Content-Type}>. |
| <COOKIES(*)> | HTTP Request, TLS Request | All cookies as a string. |
| <COOKIES{name}> | HTTP Request, TLS Request | A specific cookie by name. |
| <ERROR> | Any block that throws an exception | See below. |
| <PROXY> | Runner / Debugger (when Use Proxies is on) | The current proxy as host:port only (no credentials). Cosmetic — the real proxy authentication travels inside the proxy object, not this string. |
| <PROXYFULL> | Runner / Debugger (when Use Proxies is on) | The complete proxy string host:port:user:pass (or host:port when the proxy has no authentication). Use it to reuse the authenticated proxy inside the config (scripts, a second hop, a header, …). |
The <ERROR> Variable
<ERROR> is a special hidden variable that is set whenever any block throws an unhandled exception during execution.
How it works
- A block's
Process()method throws an exception. - LoliScript catches the exception and writes
ex.MessagetoBotData.ErrorMessage. BotData.ErrorMessagewrites the value into the"ERROR"hidden variable.- Subsequent blocks (especially Keycheck) can read
<ERROR>like any other variable.
Key Difference: HTTP vs Protocol Blocks
| Block Type | On Exception |
|---|---|
| HTTP Request, Captcha, BypassCF | Sets <ERROR>, sets bot status to ERROR, stops script |
| IMAP, POP3, SMTP, FTP, TCP | Sets <ERROR>, script continues — use Keycheck to classify |
Always place a Keycheck immediately after IMAP / POP3 / SMTP / FTP blocks to handle both success and error cases. Check <ERROR> for strings like "Authentication failed", "Too many connections", "535", etc.
Example
IMAP Connect "imap.libero.it" "993" (UseSSL=True) 30000
IMAP Login "<email>" "<pass>"
KEYCHECK
KEYCHAIN Failure OR
KEY "<ERROR>" Contains "Authentication failed"
KEYCHAIN Ban OR
KEY "<ERROR>" Contains "Too many"
KEYCHAIN Success OR
KEY "<ERROR>" DoesNotExist
Single vs List Variables
Variables in BotData have one of two types:
| Type | Access syntax | Set by |
|---|---|---|
| Single | <varName> |
Most blocks — HTTP response, IMAP count, Parse (first match), Function output |
| List | <varName[0]> — first item<varName[*]> — all items joined |
Parse with "List" output, IMAP ListFolders, FTP ListFiles, Function Split |
Accessing List Items
PARSE <SOURCE> CSS ".item" ATTRIBUTE:"innerText" LIST -> "items"
# Use first item
REQUEST GET "https://api.example.com/<items[0]>"
# Use all items joined by space (for logging or keycheck)
KEYCHECK
KEYCHAIN Success OR
KEY "<items[*]>" Contains "premium"
Capture Flag
Variables can be marked as captured. Captured variables are saved alongside the hit in the Hits DB when the bot status is SUCCESS or a capture-enabled CUSTOM status.
In the Stacker UI, enable the capture toggle on any output variable field. In LoliScript, add CAP at the end of the variable name:
PARSE <SOURCE> JSON "user.plan" -> "planType" CAP
PARSE <SOURCE> JSON "user.balance" -> "balance" CAP
Both planType and balance will appear in the Hits DB entry for this bot run.
Context-Aware Variable Suggestions
OBM2 Pro analyzes all blocks above the currently selected block in the Stacker and extracts the output variable names. These names are offered as suggestions in combo-box dropdowns throughout the block UI.
How Extraction Works
The StackVariableExtractor helper (in OpenBullet/Helpers/) inspects each block in order via reflection, extracting:
VariableName— Parse, Function, IMAP, FTP, POP3OutputVariable— HTTP Request, TLS RequestVarName— Utility
Captcha blocks always contribute the fixed names: CAPTCHAID, SOLUTION, GT_CHALLENGE, GT_VALIDATE, GT_SECCODE.
Suggestions update every time you select a block in the Stacker, not only on initial load. If you add a new Parse block above the current one, deselect and reselect the block to refresh the dropdown.
Variable Syntax Reference
| Syntax | Meaning |
|---|---|
<varName> | Value of a Single variable |
<varName[0]> | First element of a List variable |
<varName[2]> | Third element (0-based index) |
<varName[*]> | All elements of a List joined by space |
<SOURCE> | Last HTTP/browser response body |
<RESPONSECODE> | Last HTTP status code |
<ADDRESS> | Last final URL |
<HEADERS(*)> | All response headers as string |
<HEADERS{X-Auth}> | Specific header value |
<COOKIES(*)> | All cookies as string |
<COOKIES{session}> | Specific cookie value |
<ERROR> | Last exception message (empty if no error) |
<PROXY> | Current proxy as host:port (no credentials) |
<PROXYFULL> | Current proxy as host:port:user:pass (or host:port if no auth) |
Variable substitution is performed by ReplaceValues() in BlockBase before every field is used in a request or condition. This means you can embed variables in URLs, POST bodies, headers, and key values.
OBM2 Pro