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=BEGIN and //#*#SNIPPET=END, executed in the Chromium browser.
Note: //#*# directives look like JS comments but are intercepted by the engine before any JavaScript evaluation, ensuring full compatibility with standard JS editors.

Script structure

1

Header / Comment

Title, description, name of the company/target.

2

GLOBALV — Variable declaration

GLOBALV=BEGIN / END block with all the input variables.

3

Initial configuration

SCREEN_SIZE, WAIT, TARGET_FRAME=MAIN.

4

Navigation to the target URL

URL_GOTO followed by WAIT for the page to load.

5

Interaction with the page

Sequence of SNIPPET, MOUSE_CLICK, WRITETO, IF/ELSE/ENDIF, WAIT.

6

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=BEGIN and SNIPPET=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.
⚠ Warning: JavaScript code outside SNIPPET blocks is not executed in the browser. All JS that needs to run must be placed inside a SNIPPET block.

GLOBALV — Global variables

data
//#*#GLOBALV=BEGIN … //#*#GLOBALV=ENDDeclares the script's variables
Defines the script's global variable block. Everything between GLOBALV=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=BEGIN var marca="HONDA"; var modello="XL 650 V TRANSALP"; var data_nasc="10/01/1986"; var cu="1"; //#*#GLOBALV=END

GLOBALV=INJECT

javascript
//#*#GLOBALV=INJECTInjects the variables into the browser's JS context
Executes the text of the GlobalV 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 //#*#WAIT=1 //#*#SNIPPET=BEGIN document.getElementById('inputMarca').value = marca; //#*#SNIPPET=END
💡 Best practice: Re-inject GLOBALV=INJECT after every navigation to a new page.

Interpolation {{{VAR}}}

data

Variables 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.

//#*#WRITETO="TEXT={{{MARCA}}}{{TAB}}"&"CHAR_INT_MS=200" // If the placeholder encloses a JS expression, it is evaluated at runtime: //#*#WRITETO="ELEMENTID={{{document.querySelector('.active').id}}}"&"TEXT=ciao"

HTTP_GET / HTTP_POST

http
//#*#HTTP_GET=... / //#*#HTTP_POST=...Calls an HTTP endpoint from the script
Performs a synchronous HTTP call from the script thread and, if the VAR 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.
Immediate injection: If you specify 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

ParameterTypeDescription
URLstringEndpoint to call. Required.
VARstringName of the GLOBALV variable in which to save the response.
BODYstringPayload 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.
CONTENTTYPEstringContent-Type of the POST, for example application/json or application/x-www-form-urlencoded.
TIMEOUTMSintegerConnection/response timeout in milliseconds. Default: 30000.
HEADER_NamestringAdds an HTTP header. Underscores in the name are converted to dashes, for example HEADER_X_API_KEY becomes X-API-KEY.
Note: The parser only splits parameters when, after &, it finds a known key, so query strings and form-urlencoded bodies can contain &. CONTENTTYPE has an equivalent alias, CONTENT_TYPE.
⚠ Warning: the list of known keys is shared with the DOWNLOAD_UPLOAD parser and also includes 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.
Placeholders: {{{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.
//#*#GLOBALV=BEGIN var api_key="..."; var request_id="ABC123"; var val1="pippo"; var val2="pluto"; //#*#GLOBALV=END //#*#HTTP_GET="URL=https://api.example.test/status?id={{{request_id}}}"&"VAR=http_response"&"HEADER_X_API_KEY={{{api_key}}}"&"TIMEOUTMS=45000" //#*#HTTP_GET="URL=https://api.example.test/status"&"VAR=http_response"&"BODY=id={{{request_id}}}&json=1" //#*#HTTP_POST="URL=https://api.example.test/jobs"&"VAR=http_response"&"CONTENTTYPE=application/json"&"HEADER_X_API_KEY={{{api_key}}}"&"BODY={"id":"{{{request_id}}}"}" //#*#HTTP_POST="URL=https://api.example.test/form"&"VAR=http_response"&"CONTENTTYPE=application/x-www-form-urlencoded"&"BODY=var1={{{val1}}}&var2={{{val2}}}" //#*#GLOBALV=INJECT //#*#SNIPPET=BEGIN console.log(http_response); //#*#SNIPPET=END
Warning: Do not put keys or tokens directly in shared scripts. Use local variables or external configuration when the script needs to be versioned.

DOWNLOAD_UPLOAD ⚠️ not active

http
⚠ Not yet wired into the parser: ExecuteDownloadUploadCommand 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.
//#*#DOWNLOAD_UPLOAD=...Sends the next completed download as a multipart POST
Configures automatic upload of the next file downloaded by the browser. The download is still handled by Chromium, so it uses the site's session/cookies; when CEF reports the file as complete, JuliuS sends a POST multipart/form-data to the specified endpoint.

Parameters

ParameterTypeDescription
URLstringUpload endpoint. Required.
FIELDstringName of the multipart field containing the file. Default: file.
VARstringName of the GLOBALV variable in which to save the upload's text response.
TIMEOUTMSintegerConnection/response timeout in milliseconds. Default: 120000.
HEADER_NamestringAdditional HTTP header. Underscores in the name are converted to dashes.
FORM_NamestringAdditional multipart form field, besides the file. Supports interpolation.
ONCEbooleanIf true, the configuration applies only to the next download. Default: true.
DELETE / DELETEAFTERUPLOADbooleanIf true, deletes the local file after a successful upload. Default: false.
CLEARbooleanIf true, removes the current configuration without waiting for a download.
//#*#GLOBALV=BEGIN var token="..."; var job_id="12345"; //#*#GLOBALV=END //#*#DOWNLOAD_UPLOAD="URL=https://api.example.test/files"&"FIELD=file"&"VAR=upload_response"&"HEADER_AUTHORIZATION=Bearer {{{token}}}"&"FORM_jobId={{{job_id}}}"&"ONCE=true"&"TIMEOUTMS=120000" //#*#URL_GOTO=https://sito.example.test/report/download // To disarm manually: //#*#DOWNLOAD_UPLOAD="CLEAR=true"

URL_GOTO

navigation
//#*#URL_GOTO=<url>Navigates the browser to a URL
Forces the embedded Chromium browser to navigate to the specified URL. The operation is asynchronous: always use WAIT right after it to wait for the page to finish loading before interacting with the DOM.
//#*#URL_GOTO=https://www.esempio.it/pagina-target //#*#WAIT=5

WAIT

flow control
//#*#WAIT=<seconds>Pauses execution for N whole seconds
Pauses script execution for the specified number of whole seconds. Use short waits (1–3 s) for local UI operations, and longer waits (5–15 s) after navigations or form submits with a server round-trip.
//#*#WAIT=3 //#*#WAIT=10

BACK

navigation
//#*#BACKGoes back to the previous page
Equivalent to the browser's "Back" button. Navigates to the previous page in the browser history. Always follow with a WAIT and a GLOBALV=INJECT to restore the JS context.
//#*#BACK //#*#WAIT=3 //#*#GLOBALV=INJECT

SCREEN_SIZE

navigation
//#*#SCREEN_SIZE=<width>,<height>Sets the browser panel dimensions
Resizes the embedded browser panel. All coordinates for subsequent MOUSE_CLICK and OS_BROWSER_CLICK commands must be calibrated to the resolution set with this command.
//#*#SCREEN_SIZE=1024,768

MOUSE_CLICK

CEF interaction
//#*#MOUSE_CLICK=<X>,<Y>Synthetic CEF click at browser-relative coordinates
Simulates a mouse click in the CEF browser at the specified pixel coordinates, relative to the panel. Acts through the internal CEF API. For clicks on elements that do not respond to CEF events (e.g. elements with pointer-events:none, native scrollbars, Windows dialogs) use OS_BROWSER_CLICK.
//#*#MOUSE_CLICK=374,494 //#*#WAIT=1

WRITETO

CEF interaction
//#*#WRITETO="..."&"..."Simulates keyboard typing in the CEF browser
Simulates typing text into an HTML field in the CEF browser. Parameters are separated by & and enclosed in double quotes. Supports {{{VAR}}} interpolation and special keys {{KEY}}.

Parameters

ParameterTypeDescription
ELEMENTIDstringHTML ID of the element to focus. Use none to skip focusing.
FRAMENAMEstringName of the target frame/iframe. If omitted, uses the currently focused frame.
TEXTstringText to type. Supports {{{VAR}}} and {{KEY}}.
CHAR_INT_MSintegerInterval in ms between one character and the next (default: 200).
CHAR_INT_RANDOMS / NIf 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).
⚠ Non-uniform interpolation: 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.
//#*#WRITETO="ELEMENTID=ctl00_txtNome"&"TEXT={{{NOME}}}{{TAB}}"&"CHAR_INT_MS=150" //#*#WRITETO="TEXT={{SELECT_ALL}}{{CANC}}{{{MODELLO}}}"&"CHAR_INT_MS=200"&"CHAR_INT_RANDOM=N"

Special keys

CEF interaction

Inside the TEXT parameter of the WRITETO command:

{{ENTER}}Enter (↵)
{{TAB}}Tab
{{CANC}}Delete (Canc)
{{DELETE}}Delete (alias)
{{BACK_SPACE}}Backspace (←)
{{ESC}}Escape
{{ESCAPE}}Escape (alias)
{{HOME}}Line start
{{END}}Line end
{{ARROW_DOWN}}Arrow down
{{ARROW_UP}}Arrow up
{{ARROW_LEFT}}Arrow left
{{ARROW_RIGHT}}Arrow right
{{SELECT_ALL}}Select all (Ctrl+A)
Note: the source code also has the legacy alias {{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

javascript
//#*#SNIPPET=BEGIN[&NOFRAME] … //#*#SNIPPET=ENDExecutes a JavaScript block in the browser
All code between SNIPPET=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 $('#ddlMarca').val(marca).keydown(); //#*#SNIPPET=END //#*#SNIPPET=BEGIN&NOFRAME window.scrollTo(0, 0); //#*#SNIPPET=END
⚠ Warning: SNIPPET blocks cannot be nested. Every SNIPPET=BEGIN must have its own SNIPPET=END.

EVALJS

javascript
//#*#EVALJS=<JS expression>Evaluates a JS expression and stores its result
Executes a single JavaScript expression in the browser (10 s timeout) and stores the returned value as the result of the current operation, retrievable later via API with ?operation=getresult. Designed to call extraction functions already defined in a previous SNIPPET.
//#*#EVALJS=preventivo(); //#*#EVALJS=document.getElementById("risultato").innerText

TARGET_FRAME

navigation
//#*#TARGET_FRAME=MAIN | POPUPSelects the target frame/window
Sets the execution context for subsequent commands. MAIN selects the main frame; POPUP selects a child popup window identified by the URL on the following line.
ValueDescription
MAINMain frame of the current browser window.
POPUPChild popup. Must be followed by //#*#TARGET_URL=<url>.
//#*#TARGET_FRAME=MAIN //#*#TARGET_FRAME=POPUP //#*#TARGET_URL=https://www.esempio.it/popup-login

TARGET_URL matching rules

ValueBehavior
* or emptyUses the last active popup (no URL matching).
Exact URLLooks for a popup whose URL matches exactly.
Partial URLIf no exact match is found, looks for a popup whose URL contains the specified value (substring match).
⚠ Warning: If the popup with the specified URL is not open, the engine throws an exception and stops the script.

IF / ELSE / ENDIF

flow control
//#*#IF= … //#*#ELSE … //#*#ENDIFConditional execution based on a JS expression
Allows conditional execution of blocks of directives. The expression after IF= 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.

// Basic example: IF without ELSE //#*#IF=document.querySelector('#btnAccetta') !== null //#*#SNIPPET=BEGIN document.querySelector('#btnAccetta').click(); //#*#SNIPPET=END //#*#WAIT=2 //#*#ENDIF // Example with ELSE //#*#IF=document.querySelector('.errore-pagina') !== null //#*#PAUSE // there's an error: suspend for manual intervention //#*#ELSE //#*#SNIPPET=BEGIN $('#btnAvanti').click(); //#*#SNIPPET=END //#*#WAIT=8 //#*#ENDIF // Example with GlobalV variables //#*#IF=guida === "Libera" //#*#SNIPPET=BEGIN $('#rdoGuidaLibera').click(); //#*#SNIPPET=END //#*#ENDIF // Example with nested IFs //#*#IF=cu < 5 //#*#IF=guida === "Libera" //#*#MOUSE_CLICK=200,300 //#*#ELSE //#*#MOUSE_CLICK=250,300 //#*#ENDIF //#*#ENDIF
Technical notes: The expression is evaluated via 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
//#*#PAUSESuspends execution until manually resumed
Suspends script execution until the user manually resumes it (via the UI or the ?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.
Not only manual resume: if the Captcha Interceptor is active and a remote resolver sends a '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.
//#*#IF=document.querySelector('.captcha-box') !== null //#*#PAUSE // suspend: the operator solves the captcha //#*#ENDIF

Comments

flow control

JuliuS supports both JavaScript comment syntaxes. /* ... */ blocks are useful for temporarily disabling entire sections, including JuliuS directives.

// Single-line comment — ignored by the engine /* Multi-line block — everything between /* and */ is skipped by the JuliuS engine, including any //#*# directives within it. */

CAPTURE_SCREENSHOT

CEF output
//#*#CAPTURE_SCREENSHOTScreenshot of the CEF browser panel
Captures the current visual state of the CEF browser and saves the JPG file in the Settings.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.
//#*#CAPTURE_SCREENSHOT //#*#SNIPPET=BEGIN $('#btnAvanti').click(); //#*#SNIPPET=END

OS_SCREENSHOT

OS output
//#*#OS_SCREENSHOT[=fileName]Screenshot of the entire Windows desktop
Captures the entire Windows desktop (not just the CEF browser) and saves the JPG file. Useful for capturing native dialogs, system popups, and any window outside the browser. The generated path is added to the operation result's screenShotList.
VariantDescription
//#*#OS_SCREENSHOTAutomatic file name: ExcelLogLineNameBase_OS_N.jpg
//#*#OS_SCREENSHOT=fileNameCustom file name: fileName.jpg
//#*#OS_SCREENSHOT //#*#OS_SCREENSHOT=popup_conferma
Difference from CAPTURE_SCREENSHOT: CAPTURE_SCREENSHOT only captures the CEF panel. OS_SCREENSHOT captures the entire Windows desktop, including native windows, taskbar, and system popups.

Result function

javascript

To 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.

//#*#SNIPPET=BEGIN function preventivo() { var el = document.querySelector('#tabs-Proposta0-label font'); return el ? el.innerHTML : 'non trovato'; } //#*#SNIPPET=END //#*#WAIT=2 //#*#EVALJS=preventivo(); // Retrieve via API: GET /?operation=getresult // GET /?getresult=preventivo
Response format: the response of 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.
Out of scope: the JuliuS HTTP server also exposes other 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 — mouse
//#*#OS_MOUSE_MOVE=<X>,<Y>Moves the cursor to absolute screen coordinates
Moves the mouse cursor to absolute screen coordinates using operating system APIs. Acts on the entire desktop, not just the CEF browser. Useful for interacting with native Windows dialogs, system popups, or other applications.
//#*#OS_MOUSE_MOVE=640,480 //#*#WAIT=1

OS_MOUSE_CLICK

OS — mouse
//#*#OS_MOUSE_CLICKLeft click at the current OS cursor position
Simulates a left mouse click at the current position of the system cursor. Use after OS_MOUSE_MOVE. Acts at the OS level and can interact with any window visible on the desktop.
//#*#OS_MOUSE_MOVE=500,350 //#*#OS_MOUSE_CLICK

OS_MOUSE_RCLICK

OS — mouse
//#*#OS_MOUSE_RCLICKRight click at the current OS cursor position
Simulates a right mouse click at the current position of the system cursor, to open native OS context menus or those of Windows applications.
//#*#OS_MOUSE_MOVE=500,350 //#*#OS_MOUSE_RCLICK //#*#WAIT=1

OS_MOUSE_MOVE_CLICK

OS — mouse
//#*#OS_MOUSE_MOVE_CLICK=<X>,<Y>OS move + left click in a single instruction
Combines OS_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_MOVE_CLICK=640,400 //#*#WAIT=1

OS_MOUSE_DOUBLE_CLICK

OS — mouse
//#*#OS_MOUSE_DOUBLE_CLICK=<X>,<Y>Double click at absolute screen coordinates
Moves the cursor to X,Y and performs two quick left clicks (with an 80ms pause between them) to simulate a native operating system double click. Uses absolute screen coordinates.
//#*#OS_MOUSE_DOUBLE_CLICK=300,200 //#*#WAIT=1

OS_MOUSE_MOVE_PATH

OS — mouse
//#*#OS_MOUSE_MOVE_PATH=x1,y1,d1;x2,y2,d2;...Moves the OS cursor along a sequence of points
Moves the operating system cursor through a sequence of points, to simulate a more natural mouse movement compared to a single jump. It is the directive automatically generated by the Macro Recorder in "Uman" mode (see Macro Recorder), but it can also be used hand-written.
Syntax: list of x,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_MOUSE_MOVE_PATH=300,200,0;340,210,40;380,225,40;420,240,40 //#*#WAIT=1

OS_BROWSER_CLICK

OS — mouse
//#*#OS_BROWSER_CLICK=<X>,<Y>OS click at coordinates relative to the browser panel
Performs a left click at the operating system level using coordinates relative to the CEF browser panel — the same origin as MOUSE_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

DirectiveClick typeCoordinatesWhen to use it
MOUSE_CLICKInternal CEFBrowser-relativeGeneral case: standard DOM elements
OS_MOUSE_MOVE_CLICKOSAbsolute screenClicks on windows outside the browser
OS_BROWSER_CLICKOSBrowser-relativeElements that do not respond to CEF, scrollbars, native dropdowns, pointer-events:none
//#*#OS_BROWSER_CLICK=374,494 //#*#WAIT=1

OS_BROWSER_INFO

OS — debug
//#*#OS_BROWSER_INFOWrites the window and browser coordinates to the log
Writes to the JuliuS log the position and size information of the main window and the CEF browser panel, including absolute screen coordinates and the DPI scale factor. Produces no output in the script and does not interact with the browser. It is a development and debugging tool: useful for calibrating the absolute coordinates to use in the OS_MOUSE_MOVE and OS_MOUSE_MOVE_CLICK commands.
//#*#OS_BROWSER_INFO // Example log output: // [OS_BROWSER_INFO] {"mainForm":{"left":100,"top":50,"width":1200,"height":800}, // "browser":{"left":0,"top":60,"width":1024,"height":768, // "screenLeft":100,"screenTop":110},"scaleFactor":1.25}

OS_KEY_PRESS

OS — keyboard
//#*#OS_KEY_PRESS=<keycode>Presses a key via numeric VK keycode
Sends a key press to the active operating system window via its Virtual Key keycode. Unlike WRITETO, 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.
KeycodeKeyKeycodeKey
13ENTER27ESC
9TAB32SPACE
8BACKSPACE46DELETE
37← LEFT38↑ UP
39→ RIGHT40↓ DOWN
112–123F1–F1265–90A–Z
//#*#OS_KEY_PRESS=13 // ENTER //#*#OS_KEY_PRESS=27 // ESC

OS_KEY

OS — keyboard
//#*#OS_KEY=<key_name>Presses a key by name (readable alternative to OS_KEY_PRESS)
A more readable alternative to OS_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.
ValueKeyValueKey
enterENTEResc / escapeESC
tabTABbackspaceBACKSPACE
spaceSPACEarrow_up
arrow_downarrow_left
arrow_right
//#*#OS_KEY=enter //#*#OS_KEY=arrow_down //#*#OS_KEY=tab

OS_KEY_COMBO

OS — keyboard
//#*#OS_KEY_COMBO=<modifier>+<key>OS key combination (Ctrl/Shift/Alt + key)
Simulates an OS-level key combination via keybd_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.
FieldAccepted values
modifierctrl, shift, alt
keySingle letter (az), or: f4f12, tab, enter, esc, del, home, end, pageup, pagedown
//#*#OS_KEY_COMBO=ctrl+c // Copy //#*#OS_KEY_COMBO=ctrl+v // Paste //#*#OS_KEY_COMBO=ctrl+a // Select all //#*#OS_KEY_COMBO=alt+f4 // Close window //#*#OS_KEY_COMBO=shift+tab // Reverse tab

RNDWAIT

flow control
//#*#RNDWAIT=<seconds>Random wait to simulate human behavior
Waits a randomly chosen number of seconds in the range [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=10 // waits between 5s and 10s (random) //#*#RNDWAIT=6 // waits between 3s and 6s (random)
💡 Best practice: use RNDWAIT on long pauses and keep WAIT=1 for short synchronizations where variability is not needed.

CAPTCHA_Y

flow control
//#*#CAPTCHA_Y=<pixel>Y scroll coordinate to center the captcha
Sets the Y coordinate in pixels to scroll the page to when the captcha interceptor detects an active captcha. Used to bring the captcha div to the center of the screen before JuliuS sends the image to the automatic resolver.
//#*#CAPTCHA_Y=350 // scrolls to Y=350 to center the captcha
⚠ Warning: it must be placed before navigating to the page that contains the captcha. If omitted, JuliuS uses the coordinate configured in the global settings (Settings.Data.captchaScrollCoordComma).

Captcha Interceptor & Solver Bridge

application feature
Not a //#*# 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:

//#*#SNIPPET=BEGIN var reqId = crypto.randomUUID(); myextension.solverRequest(reqId, 'image_b64', base64Immagine); //#*#SNIPPET=END //#*#WAIT=3 //#*#EVALJS=window.__juliusSolver && window.__juliusSolver.responses['ID_GENERATO'] ? window.__juliusSolver.responses['ID_GENERATO'].answer : ''

The response arrives asynchronously in window.__juliusSolver.responses[reqId] = {success, answer, error} (or via a callback registered in window.__juliusSolver.callbacks[reqId]).

⚠ Current implementation note: in the code, this bridge does not go through the WSS channel described above — it is temporarily wired (explicit bypass, commented as "TEST DIRETTO" in the source) to a hardcoded local Ollama server (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

session
//#*#RESTART_CHROMIUMIn-memory reset of the Chromium session
Performs an in-memory reset of the Chromium session without physically restarting the browser, via the DevTools Protocol: navigates to about: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().
//#*#RESTART_CHROMIUM //#*#WAIT=2 //#*#URL_GOTO=https://... //#*#WAIT=5 //#*#GLOBALV=INJECT
When to use it: to get a clean session between one quote and the next without the overhead of disk cleanup.

DELETE_CHROMIUM_CACHE

session
//#*#DELETE_CHROMIUM_CACHEDeep reset: in-memory + on-disk cache
Deep reset: clears everything in-memory via DevTools (like RESTART_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().
//#*#DELETE_CHROMIUM_CACHE //#*#WAIT=2 //#*#URL_GOTO=https://...
RESTART_CHROMIUMDELETE_CHROMIUM_CACHE
Reset typeIn-memory (DevTools)In-memory + filesystem
Speed~3s~5s (disk I/O)
Deletes files on diskNoYes
When to useReset between one quote and the nextCorrupted cache, full pre-session reset
⚠ Warning: use only when RESTART_CHROMIUM is not enough (corrupted cache, problematic persistent sessions, first start of a new work session).

Macro Recorder

recording

JuliuS 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.

1

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.

2

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').

3

Script generation

TfrmScript.RecordEvent receives the JSON and appends the corresponding JuliuS directives to the editor, parameterizing values into GLOBALV.

4

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,H lines, but only if the script header has already been generated.

Event → generated directive mapping

User eventOutput in the script
First event, empty editorFull header: GLOBALV=BEGIN/END, SCREEN_SIZE=1024,768, WAIT=1, TARGET_FRAME=MAIN, URL_GOTO=<page>, WAIT=8, GLOBALV=INJECT
First event, non-empty editorEnsures 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 idVariable in GLOBALV + //#*#WRITETO="ELEMENTID=<id>"&"TEXT={{{var}}}"&"CHAR_INT_MS=60" (fixed 60ms interval)
Input into a field without an idVariable + SNIPPET with querySelector(sel).value=var + input/change events
ClickComment // [REC] click … with alternative coordinates //#*#MOUSE_CLICK=x,y + SNIPPET with scrollIntoView() + .click() + WAIT=1
Automatic parameterization: every typed input becomes a 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.
⚠ Draft, not production-ready: jQuery UI autocomplete widgets and native dropdowns are captured as simple 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

//#*#SNIPPET=BEGIN&NOFRAME (function() { var btn = document.getElementById('onetrust-accept-btn-handler'); if (btn) { btn.click(); return; } var fallback = Array.from(document.querySelectorAll('button')) .find(function(b) { return b.textContent.trim().toLowerCase().includes('accetta'); }); if (fallback) { fallback.click(); return; } })(); //#*#SNIPPET=END //#*#WAIT=3

Re-inject variables after navigation

//#*#SNIPPET=BEGIN $('#btnAvanti').click(); //#*#SNIPPET=END //#*#WAIT=8 //#*#GLOBALV=INJECT // ← required after every navigation

Filling a dropdown with jQuery

//#*#SNIPPET=BEGIN $('#lblctl00_ddlCampo').val(variabile).keydown(); //#*#SNIPPET=END //#*#WAIT=2 //#*#SNIPPET=BEGIN $('#ulctl00_ddlCampo li a').each(function() { if ($(this).text() == variabile) { $(this).mouseenter().click(); } }); //#*#SNIPPET=END

Conditional execution with IF

Use IF to handle page variations or errors without interrupting the main flow:

// Click the button only if it is present and visible //#*#GLOBALV=INJECT //#*#IF=(function(){ var b=document.querySelector('#btnCalcola'); return b && b.offsetParent!==null; })() //#*#SNIPPET=BEGIN document.querySelector('#btnCalcola').click(); //#*#SNIPPET=END //#*#WAIT=5 //#*#ELSE //#*#OS_BROWSER_CLICK=915,684 // fallback: OS click at the coordinates //#*#WAIT=3 //#*#ENDIF

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:

// ✗ Fragile: depends on the absolute position of the window //#*#OS_MOUSE_MOVE_CLICK=1015,734 // ✓ Robust: browser-relative coordinates, independent of window position //#*#OS_BROWSER_CLICK=374,494

Complete script — template with IF

// TEMPLATE: form + condition + result extraction //#*#GLOBALV=BEGIN var nome="Mario"; var data_nasc="01/01/1985"; var guida="Libera"; //#*#GLOBALV=END //#*#SCREEN_SIZE=1024,768 //#*#TARGET_FRAME=MAIN //#*#URL_GOTO=https://www.esempio.it/form //#*#WAIT=5 //#*#GLOBALV=INJECT // Accept cookies (only if present) //#*#IF=document.getElementById('onetrust-accept-btn-handler') !== null //#*#SNIPPET=BEGIN&NOFRAME document.getElementById('onetrust-accept-btn-handler').click(); //#*#SNIPPET=END //#*#WAIT=2 //#*#ENDIF // Fill in name //#*#WRITETO="ELEMENTID=inputNome"&"TEXT={{{NOME}}}{{TAB}}"&"CHAR_INT_MS=150" //#*#WAIT=1 // Conditional driving type //#*#IF=guida === "Libera" //#*#OS_BROWSER_CLICK=200,400 //#*#ELSE //#*#OS_BROWSER_CLICK=260,400 //#*#ENDIF //#*#WAIT=1 //#*#CAPTURE_SCREENSHOT // Submit //#*#SNIPPET=BEGIN document.getElementById('btnSubmit').click(); //#*#SNIPPET=END //#*#WAIT=10 //#*#GLOBALV=INJECT // Post-submit error handling //#*#IF=document.querySelector('.msg-errore') !== null //#*#OS_SCREENSHOT=errore_submit //#*#PAUSE //#*#ENDIF // Result extraction //#*#SNIPPET=BEGIN function preventivo() { return document.querySelector('.risultato-finale')?.innerText || ''; } //#*#SNIPPET=END //#*#WAIT=2 //#*#EVALJS=preventivo(); //#*#CAPTURE_SCREENSHOT