Write JavaScript (upcoming)
Available in version 1.1.72 (not yet live).
Use the Write JavaScript building block to run custom code with the zw
API. Your code runs inside the TaskBot runtime and can work with npm packages, variables and tables, state, device storage, and the browser context.
What You Can Do
Imports and Package Management
Install, import, manage, and use npm packages. Use standard import
statements or zw.import(options, …)
for custom options.
API zw.import()
, zw.packages.*
// @zw-run-locally
import dayjs from "[email protected]"; // auto-installs if needed
await zw.log("now", dayjs().toISOString());
// Example with options — 'isolate' scopes the package to this TaskBot only
const lodash = await zw.import({ isolate: true }, "[email protected]");
await zw.log("chunked result", lodash.chunk([1, 2, 3, 4], 2));
Reference: Imports and Package Management (upcoming)
Variables and Tables
Read from and write to variables and tables (native and Google Sheets).
API zw.getRef()
, zw.setRef()
const email = await zw.getRef({ ref_id: 3623, name: "Email" });
await zw.setRef({ ref_id: 3624, name: "Email copy", value: email });
Reference: Write and Read Variables and Tables
Local and Global State
Store and use values for the current run (local state) or across runs (global state). Stays on this device; never sent to ZeroWork servers.
API zw.state.*
, zw.globalState.*
// @zw-run-locally
// Per-run local state, cleared when the run ends
const runState = zw.state.access();
runState.runStartedAt = Date.now();
// Shared Desktop Agent global state
const globalState = zw.globalState.access();
globalState.totalRuns = (globalState.totalRuns ?? 0) + 1;
// In-browser snapshot (survives serialization)
const snapshot = await zw.state.browser.getCopy();
snapshot.runStartedAt = Date.now();
await zw.state.browser.commit(snapshot);
Reference: Local and Global State (upcoming)
Device Storage
Persist key–value data on this device. Survives restarts and reinstalls. Stays on this device; never sent to ZeroWork servers.
API zw.deviceStorage.*
const credentials = {
username: await zw.deviceStorage.get("username_salesforce"),
password: await zw.deviceStorage.get("password_salesforce"),
};
await zw.deviceStorage.set("last_login_salesforce", String(Date.now()));
Reference: Device Storage (upcoming)
Utilities
Add delays and write logs.
API zw.delay()
, zw.log()
, zw.logTemp()
await zw.log("starting run");
await zw.delay({ min: 1500, max: 2500 });
Reference: Utilities (upcoming)
Browser and Context
Launch, quit, and manage the active browser context and pages.
API zw.browserContext.*
// @zw-run-locally
// Example (abridged). See the reference for all options.
await zw.browserContext.launch({
contextControls: { keepAlive: true }, // more controls available
launchOptions: { headless: true /* proxy, userDataDir, ... */ },
contextOptions: { /* recordVideo, geolocation, ... */ },
scripts: [],
cookies: [],
onContextReady: async (context) => {
await context.route('**/*.{png,jpg,jpeg}', route => route.abort());
},
// see the reference for the full list of options
});
const contextInfo = await zw.browserContext.getContextInfo();
await zw.log("context", contextInfo);
await zw.browserContext.quit();
Reference: Browser Context (upcoming)
Metadata
Read TaskBot and agent details.
API zw.getTaskbotInfo()
, zw.getAgentInfo()
const taskbotInfo = await zw.getTaskbotInfo();
await zw.log("variables", taskbotInfo.variables);
const agent = zw.getAgentInfo();
await zw.log("agent version", agent.version);
Reference: Metadata (upcoming)
Local vs. Browser Execution
Some methods only work when the code runs locally.
To run code locally, either enable the Run locally checkbox in the building block UI or include // @zw-run-locally
anywhere in your code (top is recommended for visibility).
Example
// @zw-run-locally
await zw.log("This runs locally now");
console.log("And this will no longer be visible in the browser console.");
Fully available in browser execution
Variables and tables —
zw.getRef()
,zw.setRef()
Device storage —
zw.deviceStorage.*
Utilities —
zw.delay()
,zw.log()
,zw.logTemp()
Metadata —
zw.getTaskbotInfo()
,zw.getAgentInfo()
Available in browser with limitations
Imports and package management —
zw.import()
,zw.packages.*
Installing and managing packages is only available when running locally; using already imported packages is supported in the browser — see how here.Local and global state —
zw.state.*
,zw.globalState.*
Access to the live mutable object via*.access()
is only available locally. In the browser, you can get a snapshot with*.browser.getCopy()
and save state with*.browser.commit()
— see how here. The clear method*.clear()
is available in both local and browser execution.Browser context —
zw.browserContext.*
Largely unavailable in browser execution. Only inspection methodszw.browserContext.getContextInfo()
andzw.browserContext.getDefaults()
are supported in the browser.
Using the zw
APIs in No-Code Blocks
zw
APIs in No-Code BlocksYou can use the zw
APIs in no-code blocks, too, either as expressions ${...}
or as code blocks with return
statements $${...}
.
Exampl

Reference: Code in Inputs
Error Handling
Thrown errors are automatically saved to Error Reports in Run Reports (see Using Run Reports). Notifications, if enabled, then follow your error run notification settings (by email, Slack, or a custom webhook). This is a useful way to generate custom errors and get notified automatically.
Example
throw new Error(
"Test error to verify Error Reports in Run Reports"
);
Resulting error report

Thrown errors can also be caught by the Try-Catch building blocks, see: Try-Catch.
Notes
Old API
log()
,delay()
,setRef()
, andgetRef()
(without thezw.
prefix) still work. We recommend the new conventionzw.*
(e.g.,zw.getRef()
), but your current code will continue to run. ExistingactivePage
andtaskbotContext
will also continue to work, although they're now discouraged — preferzw.browserContext.getActivePage()
andzw.browserContext.getContext()
.
Last updated
Was this helpful?