Overview
The JuliuS scripting language is JavaScript extended with special directives. Each script is a text file (.js) made up of two coexisting types of statements:
- JuliuS directives — lines starting with
//#*#, interpreted by the Delphi engine to control the browser, timing, OS, and flow. - JavaScript blocks — pure JS code enclosed between
//#*#SNIPPET=BEGINand//#*#SNIPPET=END, executed in the Chromium browser.
//#*# directives look like JS comments but are intercepted by the engine before any JavaScript evaluation, ensuring full compatibility with standard JS editors.Script structure
Header / Comment
Title, description, name of the company/target.
GLOBALV — Variable declaration
GLOBALV=BEGIN / END block with all the input variables.
Initial configuration
SCREEN_SIZE, WAIT, TARGET_FRAME=MAIN.
Navigation to the target URL
URL_GOTO followed by WAIT for the page to load.
Interaction with the page
Sequence of SNIPPET, MOUSE_CLICK, WRITETO, IF/ELSE/ENDIF, WAIT.
Result extraction
Definition of the JS extraction function, EVALJS, CAPTURE_SCREENSHOT.
Execution cycle
The engine reads the script line by line in a separate thread. For each line:
- If it starts with
//#*#→ it is interpreted as a JuliuS directive. - If it falls between
SNIPPET=BEGINandSNIPPET=END→ it is accumulated and sent to the browser as JavaScript. - If it starts with
/*→ the engine skips all lines up to the matching*/. - Otherwise → the line is ignored by the engine.
SNIPPET blocks is not executed in the browser. All JS that needs to run must be placed inside a SNIPPET block.GLOBALV — Global variables
dataGLOBALV=BEGIN and GLOBALV=END is loaded into JuliuS's internal GlobalV list and can be injected into the browser with GLOBALV=INJECT. Each line must be a valid JavaScript declaration var name="value";. Values are extracted by the engine for interpolation with the {{{NAME}}} syntax.GLOBALV=INJECT
javascriptGlobalV block in the browser's JavaScript context. After the inject, all variables from the GLOBALV block are available as JS variables on the current page and can be used in subsequent SNIPPET blocks. Because every navigation resets the JS context, you must re-inject after each page change.GLOBALV=INJECT after every navigation to a new page.Interpolation {{{VAR}}}
dataVariables defined in GLOBALV can be interpolated into the parameters of JuliuS directives using {{{VARIABLE_NAME}}}. The engine substitutes the placeholder with the value before executing the command. Names are case-insensitive.
HTTP_GET / HTTP_POST
httpVAR parameter is given, saves the text response into GLOBALV. Parameters support {{{VAR}}} interpolation, so the URL, body, and headers can use values declared or produced during execution.VAR, JuliuS immediately injects the variable into the current browser as well. A SNIPPET immediately following can therefore read the response without waiting for a GLOBALV=INJECT. After a navigation you still need to re-inject the variables.Parameters
| Parameter | Type | Description |
|---|---|---|
| URL | string | Endpoint to call. Required. |
| VAR | string | Name of the GLOBALV variable in which to save the response. |
| BODY | string | Payload for HTTP_POST. With HTTP_GET it is appended to the URL as a query string (?BODY or &BODY if the URL already has parameters). Supports interpolation. |
| CONTENTTYPE | string | Content-Type of the POST, for example application/json or application/x-www-form-urlencoded. |
| TIMEOUTMS | integer | Connection/response timeout in milliseconds. Default: 30000. |
| HEADER_Name | string | Adds an HTTP header. Underscores in the name are converted to dashes, for example HEADER_X_API_KEY becomes X-API-KEY. |
&, it finds a known key, so query strings and form-urlencoded bodies can contain &. CONTENTTYPE has an equivalent alias, CONTENT_TYPE.FIELD, ONCE, CLEAR, DELETE, DELETEAFTERUPLOAD and FORM_*. A literal string such as &FIELD= or &DELETE= inside a BODY or a URL of HTTP_GET/HTTP_POST would be interpreted as the start of a new parameter: avoid these tokens in values, or encode them.{{{name}}} placeholders are resolved first from GLOBALV variables; if not found, JuliuS tries to evaluate them in the browser's JavaScript context with EvalJS. This allows the BODY, URL, or headers to also use values computed in a previous SNIPPET.DOWNLOAD_UPLOAD ⚠️ not active
httpExecuteDownloadUploadCommand and all the download/upload logic are implemented in uFrmScript.pas/uMainBrowser.pas, but the main script execution loop (ExecuteScript) has no StartsWith('//#*#DOWNLOAD_UPLOAD=') branch. Placing this directive in a script today has no effect at all (silent no-op). The section is kept as a reference for when the wiring is added: do not use it in production scripts until then.POST multipart/form-data to the specified endpoint.Parameters
| Parameter | Type | Description |
|---|---|---|
| URL | string | Upload endpoint. Required. |
| FIELD | string | Name of the multipart field containing the file. Default: file. |
| VAR | string | Name of the GLOBALV variable in which to save the upload's text response. |
| TIMEOUTMS | integer | Connection/response timeout in milliseconds. Default: 120000. |
| HEADER_Name | string | Additional HTTP header. Underscores in the name are converted to dashes. |
| FORM_Name | string | Additional multipart form field, besides the file. Supports interpolation. |
| ONCE | boolean | If true, the configuration applies only to the next download. Default: true. |
| DELETE / DELETEAFTERUPLOAD | boolean | If true, deletes the local file after a successful upload. Default: false. |
| CLEAR | boolean | If true, removes the current configuration without waiting for a download. |
URL_GOTO
navigationWAIT right after it to wait for the page to finish loading before interacting with the DOM.WAIT
flow controlBACK
navigationWAIT and a GLOBALV=INJECT to restore the JS context.SCREEN_SIZE
navigationMOUSE_CLICK and OS_BROWSER_CLICK commands must be calibrated to the resolution set with this command.MOUSE_CLICK
CEF interactionpointer-events:none, native scrollbars, Windows dialogs) use OS_BROWSER_CLICK.WRITETO
CEF interaction& and enclosed in double quotes. Supports {{{VAR}}} interpolation and special keys {{KEY}}.Parameters
| Parameter | Type | Description |
|---|---|---|
| ELEMENTID | string | HTML ID of the element to focus. Use none to skip focusing. |
| FRAMENAME | string | Name of the target frame/iframe. If omitted, uses the currently focused frame. |
| TEXT | string | Text to type. Supports {{{VAR}}} and {{KEY}}. |
| CHAR_INT_MS | integer | Interval in ms between one character and the next (default: 200). |
| CHAR_INT_RANDOM | S / N | If S, each interval between two characters becomes a uniform random value between 0 and CHAR_INT_MS-1 (not a variation around the configured value). |
ELEMENTID supports the fallback to JS evaluation (like HTTP_GET/HTTP_POST); the TEXT parameter supports only direct substitution of GLOBALV variables — a JS expression written inside {{{...}}} in TEXT is not evaluated at runtime.Special keys
CEF interactionInside the TEXT parameter of the WRITETO command:
{{ARROW_RIGTH}} (typo for "RIGHT"), kept for compatibility with existing scripts — in new scripts use {{ARROW_RIGHT}}. {{SELECT_ALL}} is handled at a different level from the other placeholders: it splits the text at the marker and sends the Ctrl+A combination at that point, directly inside the typing routine. Any other character not listed (including accented characters and symbols) is typed as a literal character.SNIPPET
javascriptSNIPPET=BEGIN and SNIPPET=END is executed in the Chromium browser's JavaScript context. It is the main mechanism for interacting with the DOM. The NOFRAME option forces execution in the main frame (window) instead of the currently focused frame.SNIPPET=BEGIN must have its own SNIPPET=END.EVALJS
javascript?operation=getresult. Designed to call extraction functions already defined in a previous SNIPPET.TARGET_FRAME
navigationMAIN selects the main frame; POPUP selects a child popup window identified by the URL on the following line.| Value | Description |
|---|---|
| MAIN | Main frame of the current browser window. |
| POPUP | Child popup. Must be followed by //#*#TARGET_URL=<url>. |
TARGET_URL matching rules
| Value | Behavior |
|---|---|
* or empty | Uses the last active popup (no URL matching). |
| Exact URL | Looks for a popup whose URL matches exactly. |
| Partial URL | If no exact match is found, looks for a popup whose URL contains the specified value (substring match). |
IF / ELSE / ENDIF
flow controlIF= is evaluated in the browser via EvalJS: if the result is truthy, the IF block is executed and the ELSE block is skipped; if it is falsy, the IF block is skipped and the (optional) ELSE block is executed. The ELSE block is optional. IF statements can be nested: the engine correctly manages the nesting depth.Values considered falsy
Empty string "", "false", "0", "null", "undefined". Any other value is considered truthy.
EvalJS on the main thread. Variables injected with GLOBALV=INJECT are available in the expression. The evaluation result is written to the JuliuS log to make debugging easier (IF [expr] = value → true/false).PAUSE
flow control?operation=start API). Useful for manual intervention (e.g. captcha solving, manual login) at critical points in the flow. Often used in combination with IF to suspend only in case of anomalous conditions.'go' message via WSS, the script unblocks and resumes automatically. Safety timeout: if no remote activity arrives for more than 120s, JuliuS exits the pause anyway.CAPTURE_SCREENSHOT
CEF outputSettings.Data.screenShotPath folder. The file name is built automatically as ExcelLogLineNameBase_N.jpg. The path is added to the screenShotList of the operation result, retrievable via API. If TARGET_FRAME=POPUP is active at the time of capture, the full page of the current popup is saved instead of the main browser window.OS_SCREENSHOT
OS outputscreenShotList.| Variant | Description |
|---|---|
//#*#OS_SCREENSHOT | Automatic file name: ExcelLogLineNameBase_OS_N.jpg |
//#*#OS_SCREENSHOT=fileName | Custom file name: fileName.jpg |
CAPTURE_SCREENSHOT only captures the CEF panel. OS_SCREENSHOT captures the entire Windows desktop, including native windows, taskbar, and system popups.Result function
javascriptTo return a result retrievable via API, define a JS function in a SNIPPET block and call it with EVALJS. By convention it is called preventivo(), but any name can be used.
operation=getresult / getresult=<name> is not the raw string returned by the function, but a JSON object with at least the fields OperationId, rawResult (the value returned by the function), StartedAt and screenShotList (list of screenshots captured during execution). The client must read rawResult from the JSON, not treat the entire response as plain text.operation= values (script control, DOM/page inspection, screenshot, OS input, network/API log) not related to the scripting language — see API HTTP Reference.OS_MOUSE_MOVE
OS — mouseOS_MOUSE_CLICK
OS — mouseOS_MOUSE_MOVE. Acts at the OS level and can interact with any window visible on the desktop.OS_MOUSE_RCLICK
OS — mouseOS_MOUSE_MOVE_CLICK
OS — mouseOS_MOUSE_MOVE and OS_MOUSE_CLICK into a single directive using absolute screen coordinates. The coordinates depend on the position of the JuliuS window on the desktop: if the window is moved, the coordinates must be recalculated. For clicks independent of window position, prefer OS_BROWSER_CLICK.OS_MOUSE_DOUBLE_CLICK
OS — mouseOS_MOUSE_MOVE_PATH
OS — mousex,y,delay triples separated by ;. delay is the time in milliseconds to wait before moving toward that point (clamped to a maximum of 400ms per segment).OS_BROWSER_CLICK
OS — mouseMOUSE_CLICK and the snapshots. Internally, JuliuS converts browser coordinates into absolute screen coordinates via ClickOnBrowserRelative, so the click works correctly regardless of where the JuliuS window is positioned on the desktop and regardless of the DPI scale factor. It is the most robust choice when you want an OS click on a browser element.When to use it versus the alternatives
| Directive | Click type | Coordinates | When to use it |
|---|---|---|---|
| MOUSE_CLICK | Internal CEF | Browser-relative | General case: standard DOM elements |
| OS_MOUSE_MOVE_CLICK | OS | Absolute screen | Clicks on windows outside the browser |
| OS_BROWSER_CLICK | OS | Browser-relative | Elements that do not respond to CEF, scrollbars, native dropdowns, pointer-events:none |
OS_BROWSER_INFO
OS — debugOS_MOUSE_MOVE and OS_MOUSE_MOVE_CLICK commands.OS_KEY_PRESS
OS — keyboardWRITETO, which writes into the CEF browser, this command acts at the OS level and works on any active window: native Windows dialogs, non-web forms, desktop applications.| Keycode | Key | Keycode | Key |
|---|---|---|---|
| 13 | ENTER | 27 | ESC |
| 9 | TAB | 32 | SPACE |
| 8 | BACKSPACE | 46 | DELETE |
| 37 | ← LEFT | 38 | ↑ UP |
| 39 | → RIGHT | 40 | ↓ DOWN |
| 112–123 | F1–F12 | 65–90 | A–Z |
OS_KEY
OS — keyboardOS_KEY_PRESS: accepts the key name instead of the numeric keycode. Acts at the operating system level on the active window. Unrecognized names are logged and ignored without interrupting the script.| Value | Key | Value | Key |
|---|---|---|---|
| enter | ENTER | esc / escape | ESC |
| tab | TAB | backspace | BACKSPACE |
| space | SPACE | arrow_up | ↑ |
| arrow_down | ↓ | arrow_left | ← |
| arrow_right | → |
OS_KEY_COMBO
OS — keyboardkeybd_event. The syntax is modifier+key in lowercase. Available only on Windows: on other platforms the command is logged as not implemented and ignored without interrupting the script.| Field | Accepted values |
|---|---|
| modifier | ctrl, shift, alt |
| key | Single letter (a–z), or: f4–f12, tab, enter, esc, del, home, end, pageup, pagedown |
RNDWAIT
flow control[N div 2 .. N]. Use instead of fixed WAIT values on long pauses (form submits, page loads) to reduce the risk of anti-bot detection.RNDWAIT on long pauses and keep WAIT=1 for short synchronizations where variability is not needed.CAPTCHA_Y
flow controlSettings.Data.captchaScrollCoordComma).Captcha Interceptor & Solver Bridge
application feature//#*# directive: it is an application-level system, configured in Settings, documented here as context because it affects the runtime behavior of PAUSE and CAPTCHA_Y.Captcha Interceptor + remote operator via WSS
Two independent toggles in Settings: AI Resolver (enables automatic captcha detection) and WSS (enables the connection to the remote WebSocket server, configurable address). When the focused frame corresponds to a captcha (excluding invisible badges), JuliuS centers the view on the CAPTCHA_Y coordinate and sends live screenshots to the remote resolver via WSS. A connected operator/resolver can click and scroll remotely on the JuliuS browser; once solved, it sends a 'go' message that automatically unblocks any ongoing PAUSE and resumes the script. If no remote activity arrives for more than 120s, JuliuS exits the pause anyway.
Solver Bridge — API callable from SNIPPET
Unlike the channel above, this is a JavaScript API usable directly inside a SNIPPET block, independent of the "AI Resolver" toggle:
The response arrives asynchronously in window.__juliusSolver.responses[reqId] = {success, answer, error} (or via a callback registered in window.__juliusSolver.callbacks[reqId]).
qwen3-vl:8b, OCR endpoint) instead of the remote resolver via WSS. Check the state of the code before relying on this path for production scripts.RESTART_CHROMIUM
sessionabout:blank, Network.clearBrowserCache, Network.clearBrowserCookies, Storage.clearDataForOrigin (localStorage/sessionStorage/IndexedDB), reapplies Chromium preferences, and returns to about:blank. Automatically waits ~3s for reinitialization. Also exposed as the MCP tool julius_restart_chromium().DELETE_CHROMIUM_CACHE
sessionRESTART_CHROMIUM) and then physically deletes the cache directory on disk (GlobalCEFApp.RootCache). Automatically waits ~4s (longer than RESTART_CHROMIUM due to filesystem I/O). Also exposed as the MCP tool julius_delete_chromium_cache().| RESTART_CHROMIUM | DELETE_CHROMIUM_CACHE | |
|---|---|---|
| Reset type | In-memory (DevTools) | In-memory + filesystem |
| Speed | ~3s | ~5s (disk I/O) |
| Deletes files on disk | No | Yes |
| When to use | Reset between one quote and the next | Corrupted cache, full pre-session reset |
RESTART_CHROMIUM is not enough (corrupted cache, problematic persistent sessions, first start of a new work session).Macro Recorder
recordingJuliuS can generate the script automatically by observing the user's real interactions on the embedded browser. It is activated with the ToggleSwitch REC in the Script window. It is the fastest way to get a working draft to refine.
Activation (REC → ON)
A JS listener is injected into the main frame, named iframes, and TChildForm popups. It protects itself against double installation (window.__jrInstalled) and stays inert until window.__jrActive is true.
Event capture
Intercepts click and change events in the capture phase, builds a stable CSS selector (#id or cssPath with :nth-of-type/[name]), and sends a JSON payload via myextension.sendresulttobrowser(json, 'jsRecordEvent').
Script generation
TfrmScript.RecordEvent receives the JSON and appends the corresponding JuliuS directives to the editor, parameterizing values into GLOBALV.
Deactivation (REC → OFF)
Sets window.__jrActive=false on all frames; the listener stays installed but inert.
"Uman" mode
A second ToggleSwitch (separate from REC) enables, when REC is active, also recording of the real mouse movement at the operating system level:
- Movement is sampled from an already-installed global OS hook, with throttling of about 1 sample every 40ms and discarding movements smaller than 6px.
- Points are buffered (up to 50) and, just before the next recorded click or input, they are emitted in a single
//#*#OS_MOUSE_MOVE_PATH=...line (see dedicated section). - Resizing the browser panel during recording also generates
//#*#SCREEN_SIZE=W,Hlines, but only if the script header has already been generated.
Event → generated directive mapping
| User event | Output in the script |
|---|---|
| First event, empty editor | Full header: GLOBALV=BEGIN/END, SCREEN_SIZE=1024,768, WAIT=1, TARGET_FRAME=MAIN, URL_GOTO=<page>, WAIT=8, GLOBALV=INJECT |
| First event, non-empty editor | Ensures a GLOBALV block exists and appends the actions |
| Wait between two actions | //#*#WAIT=N proportional to the real seconds (integer part, emitted only if ≥1s, clamped to 1–20s) |
| URL change | //#*#GLOBALV=INJECT |
| Frame / popup change | //#*#TARGET_FRAME=<frame>; for popups, TARGET_FRAME=POPUP + TARGET_URL=* |
| Window resize ("Uman" mode) | //#*#SCREEN_SIZE=W,H |
| Real mouse movement ("Uman" mode) | //#*#OS_MOUSE_MOVE_PATH=x1,y1,d1;x2,y2,d2;..., emitted right before the next click/input |
Input into a field with an id | Variable in GLOBALV + //#*#WRITETO="ELEMENTID=<id>"&"TEXT={{{var}}}"&"CHAR_INT_MS=60" (fixed 60ms interval) |
Input into a field without an id | Variable + SNIPPET with querySelector(sel).value=var + input/change events |
| Click | Comment // [REC] click … with alternative coordinates //#*#MOUSE_CLICK=x,y + SNIPPET with scrollIntoView() + .click() + WAIT=1 |
GLOBALV variable (name derived from id/name: non-alphanumeric characters → _, prefix v_ if the name starts with a digit, duplicates made unique with a _N suffix). Retyping into the same field updates the same variable instead of creating a new one.change events. Refine by replacing them with cascading dropdown patterns, add cookie/captcha handling, and the result-extraction preventivo() function.Best practices
Cookie banner handling
Re-inject variables after navigation
Filling a dropdown with jQuery
Conditional execution with IF
Use IF to handle page variations or errors without interrupting the main flow:
OS click with browser-relative coordinates
Prefer OS_BROWSER_CLICK over OS_MOUSE_MOVE_CLICK so you don't have to recalculate absolute coordinates if the window is moved:
Comments
flow controlJuliuS supports both JavaScript comment syntaxes.
/* ... */blocks are useful for temporarily disabling entire sections, including JuliuS directives.