Official JavaScript SDK for InstaVM API
npm install instavmA comprehensive JavaScript/TypeScript client library for InstaVM's code execution and browser automation APIs.
- Code Execution: Run Python, Bash, and other languages in secure cloud environments
- Browser Automation: Control web browsers for testing, scraping, and automation
- Session Management: Automatic session creation and persistent execution contexts
- File Operations: Upload files to execution environments
- Async Support: Execute commands asynchronously for long-running tasks
- Error Handling: Comprehensive exception hierarchy for different failure modes
- TypeScript Support: Full type safety with comprehensive TypeScript definitions
- Modern JavaScript: ES modules, CommonJS, and UMD support
``bash`
npm install instavm
`typescript
import { InstaVM, ExecutionError, NetworkError } from 'instavm';
// Create client with automatic session management
const client = new InstaVM('your_api_key');
try {
// Execute a command
const result = await client.execute("print(100**100)");
console.log(result);
// Get usage info for the session
const usage = await client.getUsage();
console.log(usage);
} catch (error) {
if (error instanceof ExecutionError) {
console.log(Code execution failed: ${error.message});Network issue: ${error.message}
} else if (error instanceof NetworkError) {
console.log();`
}
} finally {
await client.dispose();
}
Run code execution against a local container (e.g., coderunner) instead of the cloud API:
`typescript
import { InstaVM } from 'instavm';
// Create client in local mode (no API key required)
const client = new InstaVM('', {
local: true,
localURL: 'http://coderunner.local:8222' // Optional, defaults to this URL
});
// Execute code locally without session management
const result = await client.execute("print('Hello from local container!')");
console.log(result.stdout);
// Browser automation in local mode (no session required)
const content = await client.browser.extractContent({
url: 'https://example.com',
includeInteractive: true,
includeAnchors: true
});
console.log('Page title:', content.readableContent.title);
console.log('Clean content:', content.readableContent.content);
`
Note: Local mode supports:
- ✅ Code execution (execute())browser.navigate()
- ✅ Browser navigation ()browser.extractContent()
- ✅ Content extraction ()
Local mode does NOT support (cloud-only features):
- ❌ Session management (createSession(), closeSession(), getUsage())
- ❌ File upload/download
- ❌ Async execution
- ❌ Browser session creation and complex interactions
`typescript
import { InstaVM } from 'instavm';
const client = new InstaVM('your_api_key');
// Create a session first (required for upload)
await client.createSession();
// Upload files to the execution environment
const files = [
{
name: 'script.py',
content: 'print("Hello from uploaded file!")',
path: '/remote/path/script.py'
}
];
const result = await client.upload(files);
console.log(result);
// Execute the uploaded file
const execution = await client.execute('python /remote/path/script.py', {
language: 'bash'
});
console.log(execution.stdout);
`
`typescript
import { InstaVM } from 'instavm';
import fs from 'fs';
const client = new InstaVM('your_api_key');
// Create a file in the remote environment
await client.execute(
import pandas as pd
df = pd.DataFrame({'name': ['Alice', 'Bob'], 'age': [25, 30]})
df.to_csv('data.csv', index=False));
// Download the file
const result = await client.download('data.csv');
console.log(Downloaded ${result.size} bytes);
// Save to local file
fs.writeFileSync('local-data.csv', result.content);
`
`typescript
import {
InstaVM,
AuthenticationError,
RateLimitError,
SessionError,
QuotaExceededError
} from 'instavm';
try {
const client = new InstaVM('invalid_key');
await client.execute('print("test")');
} catch (error) {
if (error instanceof AuthenticationError) {
console.log("Invalid API key");
} else if (error instanceof RateLimitError) {
console.log(Rate limit exceeded - retry after ${error.retryAfter} seconds);Session error: ${error.message}
} else if (error instanceof QuotaExceededError) {
console.log("Usage quota exceeded");
} else if (error instanceof SessionError) {
console.log();`
}
}
`typescript
import { InstaVM } from 'instavm';
const client = new InstaVM('your_api_key');
// Execute command asynchronously (returns task ID)
const result = await client.executeAsync("sleep 5 && echo 'Long task complete!'", {
language: 'bash'
});
const taskId = result.taskId;
console.log(Task ${taskId} is running in background...);
// Poll for task result
const taskResult = await client.getTaskResult(taskId, 2, 30);
console.log('Task complete!');
console.log(Stdout: ${taskResult.stdout});Stderr: ${taskResult.stderr}
console.log();`
`typescript
import { InstaVM } from 'instavm';
const client = new InstaVM('your_api_key');
// Create browser session
const session = await client.browser.createSession({
viewportWidth: 1920,
viewportHeight: 1080
});
// Navigate to website
await session.navigate('https://example.com');
// Take screenshot
const screenshot = await session.screenshot();
console.log(Screenshot captured: ${screenshot.length} chars);
// Extract page data
const elements = await session.extractElements('h1, p', ['text', 'href']);
console.log('Page content:', elements);
// Clean up
await session.close();
`
`typescript
// Navigate with options
await session.navigate('https://github.com/login', {
waitTimeout: 30000,
waitUntil: 'networkidle'
});
// Fill login form
await session.fill('input[name="login"]', 'username');
await session.fill('input[name="password"]', 'password');
// Click submit button
await session.click('input[type="submit"]');
// Wait for navigation
await session.wait({ type: 'navigation' });
// Scroll to load more content
await session.scroll({ y: 1000 });
// Extract dynamic content
const repos = await session.extractElements('.repo-list-item', ['text']);
console.log('Repositories found:', repos.length);
`
`typescript
// Create session with custom options
const session = await client.browser.createSession({
viewportWidth: 1280,
viewportHeight: 720,
userAgent: 'CustomBot/1.0'
});
// Session supports event listeners
session.on('navigation', (result) => {
console.log(Navigated to: ${result.url});Page title: ${result.title}
console.log();
});
session.on('error', (error) => {
console.error('Session error:', error.message);
});
session.on('close', () => {
console.log('Session closed');
});
// Check if session is still active
if (session.isActive) {
await session.navigate('https://example.com');
}
`
`typescript
// Use browser session with automatic cleanup
const client = new InstaVM('your_api_key');
async function automateWebsite() {
const session = await client.browser.createSession();
try {
await session.navigate('https://httpbin.org/forms/post');
// Fill and submit form
await session.fill('input[name="custname"]', 'John Doe');
await session.fill('input[name="custtel"]', '555-1234');
await session.click('input[type="submit"]');
// Wait for result
await session.wait({ type: 'visible', selector: 'pre' });
// Extract result
const result = await session.extractElements('pre', ['text']);
return result[0]?.text;
} finally {
await session.close();
}
}
const result = await automateWebsite();
console.log('Form submission result:', result);
`
Combine code execution with browser automation for powerful workflows:
`typescript
import { InstaVM } from 'instavm';
const client = new InstaVM('your_api_key');
// Execute Python code to prepare data
const dataPrep = await client.execute(
import json
import pandas as pd
);const searchData = JSON.parse(dataPrep.stdout.trim());
// Use browser to search and collect results
const session = await client.browser.createSession();
const results = [];
for (const term of searchData.terms) {
await session.navigate(
https://news.ycombinator.com/search?q=${encodeURIComponent(term)});
const headlines = await session.extractElements('.titleline > a', ['text', 'href']);
results.push({
term,
headlines: headlines.slice(0, 5) // Top 5 results
});
}await session.close();
// Process results with Python
const analysis = await client.execute(
);console.log(analysis.stdout);
await client.dispose();
`Language Support
$3
`typescript
// Python with libraries
const result = await client.execute();console.log(result.stdout);
`$3
`typescript
// System operations
const sysInfo = await client.execute(, { language: 'bash' });console.log(sysInfo.stdout);
`$3
`typescript
// Variables persist across executions within the same session
await client.execute('data = [1, 2, 3, 4, 5]');
await client.execute('total = sum(data)');const result = await client.execute('print(f"Total: {total}, Average: {total/len(data)}")');
console.log(result.stdout); // Output: Total: 15, Average: 3.0
`$3
`typescript
// Check if current session is still active
const isActive = await client.isSessionActive();
console.log(Session active: ${isActive});// Check specific session
const isOtherActive = await client.isSessionActive('session-id-123');
console.log(
Other session active: ${isOtherActive});
`Advanced Features
$3
`typescript
// Wait for element to appear
await session.wait({
type: 'visible',
selector: '.loading-complete',
timeout: 30000
});// Wait for element to disappear
await session.wait({
type: 'hidden',
selector: '.spinner'
});
// Wait for page load
await session.wait({
type: 'networkidle'
});
// Simple timeout
await session.wait({
type: 'timeout',
ms: 5000
});
`$3
`typescript
// Full page screenshot
const fullPage = await session.screenshot({
fullPage: true,
format: 'png'
});// Clip specific area
const clipped = await session.screenshot({
clip: {
x: 0,
y: 0,
width: 800,
height: 600
},
format: 'jpeg',
quality: 90
});
// Screenshots return base64 encoded strings
const buffer = Buffer.from(fullPage, 'base64');
// Save to file if needed
`$3
`typescript
// Extract multiple attributes
const links = await session.extractElements('a', ['href', 'text', 'title']);// Extract with CSS selectors
const articles = await session.extractElements('article h2, .post-title', ['text']);
// Extract form data
const formData = await session.extractElements('input, select, textarea', [
'name', 'value', 'type', 'placeholder'
]);
console.log('Links found:', links);
console.log('Articles:', articles);
console.log('Form fields:', formData);
`$3
`typescript
// Extract clean, LLM-optimized content from a webpage
const content = await session.extractContent({
includeInteractive: true, // Include clickable/typeable elements
includeAnchors: true, // Include content-to-selector mappings
maxAnchors: 50 // Limit number of anchors
});// Get clean article text (no ads, no navigation, no scripts)
console.log('Title:', content.readableContent.title);
console.log('Article:', content.readableContent.content);
console.log('Author:', content.readableContent.byline);
// Find interactive elements (buttons, links, inputs)
const loginButton = content.interactiveElements?.find(
el => el.text?.toLowerCase().includes('login')
);
if (loginButton) {
await session.click(loginButton.selector);
}
// Use content anchors to map text to selectors
// Perfect for LLM agents that need to "read then click"
const signupLink = content.contentAnchors?.find(
anchor => anchor.text.toLowerCase().includes('sign up')
);
if (signupLink) {
await session.click(signupLink.selector);
}
`Error Handling Reference
$3
`typescript
import {
InstaVMError, // Base error class
AuthenticationError, // API key issues
RateLimitError, // Rate limiting (has retryAfter property)
QuotaExceededError, // Usage quota exceeded
NetworkError, // Connection issues
ExecutionError, // Code execution failures
SessionError, // Session management issues
BrowserError, // General browser errors
BrowserSessionError, // Browser session issues
BrowserInteractionError, // Browser interaction failures
BrowserTimeoutError, // Browser operation timeouts
BrowserNavigationError, // Navigation failures
ElementNotFoundError, // Element selection issues (has selector property)
UnsupportedOperationError // Operation not supported in local mode
} from 'instavm';// Specific error handling
try {
await session.click('.non-existent-button');
} catch (error) {
if (error instanceof ElementNotFoundError) {
console.log(
Element not found: ${error.selector});
} else if (error instanceof BrowserTimeoutError) {
console.log('Operation timed out');
}
}
`$3
The SDK includes automatic retry logic for:
- Network errors (connection issues)
- Rate limiting (with exponential backoff)
- Server errors (5xx status codes)
`typescript
// Customize retry behavior
const client = new InstaVM('your_api_key', {
maxRetries: 5,
retryDelay: 2000, // Base delay in milliseconds
timeout: 300000 // 5 minute timeout
});
`API Reference
$3
`typescript
class InstaVM {
constructor(apiKey: string, options?: InstaVMOptions) // Code execution
execute(command: string, options?: ExecuteOptions): Promise
executeAsync(command: string, options?: ExecuteOptions): Promise
getTaskResult(taskId: string, pollInterval?: number, timeout?: number): Promise
// File operations
upload(files: FileUpload[], options?: UploadOptions): Promise
download(filename: string, options?: DownloadOptions): Promise
// Session management
createSession(): Promise
closeSession(sessionId?: string): Promise
isSessionActive(sessionId?: string): Promise
getUsage(sessionId?: string): Promise
// Browser automation
browser: BrowserManager
// Properties
readonly sessionId: string | null
// Cleanup
dispose(): Promise
}
`$3
`typescript
interface InstaVMOptions {
baseURL?: string; // Default: 'https://api.instavm.io' (ignored if local=true)
timeout?: number; // Default: 300000 (5 minutes)
maxRetries?: number; // Default: 3
retryDelay?: number; // Default: 1000ms
local?: boolean; // Default: false - Use local container instead of cloud
localURL?: string; // Default: 'http://coderunner.local:8222' - Local container URL
}interface ExecuteOptions {
language?: 'python' | 'bash'; // Default: 'python'
timeout?: number; // Default: 15 seconds
sessionId?: string; // Use specific session
}
`$3
`typescript
class BrowserManager {
createSession(options?: BrowserSessionOptions): Promise
listSessions(): Promise
getSession(sessionId: string): Promise
getLocalSession(sessionId: string): BrowserSession | undefined
getLocalSessions(): BrowserSession[]
closeAllSessions(): Promise
dispose(): Promise
}interface BrowserSessionOptions {
viewportWidth?: number; // Default: 1920
viewportHeight?: number; // Default: 1080
userAgent?: string; // Custom user agent
}
`$3
`typescript
class BrowserSession extends EventEmitter {
// Navigation
navigate(url: string, options?: NavigateOptions): Promise
// Interaction
click(selector: string, options?: ClickOptions): Promise
type(selector: string, text: string, options?: TypeOptions): Promise
fill(selector: string, value: string, options?: FillOptions): Promise
scroll(options?: ScrollOptions): Promise
// Data extraction
screenshot(options?: ScreenshotOptions): Promise
extractElements(selector: string, attributes?: string[]): Promise
extractContent(options?: ExtractContentOptions): Promise // Utilities
wait(condition: WaitCondition, timeout?: number): Promise
close(): Promise
// Properties
readonly sessionId: string
readonly isActive: boolean
// Events: 'navigation', 'error', 'close'
}
`$3
`typescript
interface ExecutionResult {
stdout: string;
stderr: string;
success: boolean;
executionTime?: number;
cpuTime?: number;
createdAt?: string;
sessionId?: string;
error?: string;
}interface TaskResult {
stdout: string;
stderr: string;
executionTime?: number;
cpuTime?: number;
createdAt?: string;
}
interface NavigationResult {
success: boolean;
url: string;
title?: string;
status?: number;
}
interface ExtractedElement {
text?: string;
href?: string;
[attribute: string]: string | undefined;
}
type WaitCondition =
| { type: 'timeout'; ms: number }
| { type: 'visible'; selector: string }
| { type: 'hidden'; selector: string }
| { type: 'navigation' }
| { type: 'networkidle' };
`Best Practices
$3
`typescript
// Always dispose of the client when done
const client = new InstaVM('your_api_key');
try {
// Your automation code
} finally {
await client.dispose(); // Closes all sessions and cleans up
}// Or use a wrapper function
async function withInstaVM(apiKey: string, callback: (client: InstaVM) => Promise) {
const client = new InstaVM(apiKey);
try {
await callback(client);
} finally {
await client.dispose();
}
}
await withInstaVM('your_api_key', async (client) => {
const result = await client.execute('print("Hello, World!")');
console.log(result.stdout);
});
`$3
`typescript
// Implement comprehensive error handling
async function robustAutomation(client: InstaVM) {
let session: BrowserSession | null = null;
try {
session = await client.browser.createSession();
// Retry navigation with timeout
let retries = 3;
while (retries > 0) {
try {
await session.navigate('https://example.com');
break;
} catch (error) {
if (error instanceof BrowserTimeoutError && retries > 1) {
console.log(Navigation timeout, retrying... (${retries - 1} attempts left));
retries--;
await new Promise(resolve => setTimeout(resolve, 2000));
} else {
throw error;
}
}
}
// Safe element interaction
try {
await session.click('button.submit');
} catch (error) {
if (error instanceof ElementNotFoundError) {
console.log('Submit button not found, trying alternative selector');
await session.click('input[type="submit"]');
} else {
throw error;
}
}
} catch (error) {
console.error('Automation failed:', error.message);
throw error;
} finally {
if (session) {
await session.close();
}
}
}
`$3
`typescript
// Batch operations when possible
const session = await client.browser.createSession();// Instead of multiple separate calls
await session.navigate('https://example.com');
const title = await session.extractElements('title', ['text']);
const links = await session.extractElements('a', ['href']);
const images = await session.extractElements('img', ['src', 'alt']);
// Consider using a single extraction call for related elements
const pageData = await session.extractElements('title, a, img', ['text', 'href', 'src', 'alt']);
// Use appropriate timeouts
await session.navigate('https://slow-site.com', {
waitTimeout: 60000 // Increase timeout for slow sites
});
// Optimize screenshot size for performance
const thumbnail = await session.screenshot({
clip: { x: 0, y: 0, width: 400, height: 300 },
format: 'jpeg',
quality: 70
});
`CommonJS Usage
For projects using CommonJS:
`javascript
const { InstaVM, AuthenticationError } = require('instavm');async function main() {
const client = new InstaVM('your_api_key');
try {
const result = await client.execute('print("Hello from CommonJS!")');
console.log(result.stdout);
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Authentication failed');
}
} finally {
await client.dispose();
}
}
main().catch(console.error);
`Development and Testing
$3
`bash
Install dependencies
npm installRun unit tests (no API key required)
npm run test:unitRun integration tests (requires API key)
INSTAVM_API_KEY=your_api_key npm run test:integrationRun all tests
npm testBuild the package
npm run buildType checking
npm run type-check
`Note: Integration tests require a valid InstaVM API key. Set the
INSTAVM_API_KEY environment variable before running integration tests. Unit tests do not require an API key.$3
This is an official SDK. For issues and feature requests, please use the GitHub repository.
Requirements
- Node.js 16+
- TypeScript 5+ (for TypeScript projects)
License
Proprietary. This SDK is provided for use with InstaVM services only.
All rights reserved. No redistribution or modification permitted.
---
Changelog
$3
- ✅ NEW:
getTaskResult() method - Poll for async task completion with configurable intervals
- ✅ NEW: isSessionActive() method - Check if session is still active by querying VM status
- ✅ IMPROVED: Execution result format - Now returns stdout and stderr separately (matching Python SDK)
- ✅ IMPROVED: Enhanced execution results - Added cpuTime, executionTime, and createdAt fields
- ✅ IMPROVED: Better error messages - Rate limit errors now show detail field from API response
- ✅ FIXED: Session status check - Now uses /v1/sessions/status/ endpoint for accurate VM status
- ✅ UPDATED: closeSession behavior - Sessions auto-expire on server, no longer makes DELETE API call
- ✅ Full parity with Python SDK v0.8.3$3
- ✅ NEW: Local execution mode support - Run code execution against local containers
- ✅ NEW: Local browser automation - Navigate and extract content without sessions
- ✅ NEW:
UnsupportedOperationError` - Better error messages for cloud-only features- ✅ NEW: File download functionality - Download files from remote VM
- ✅ NEW: LLM-friendly content extraction - Extract clean, readable content with interactive element mapping
- ✅ Enhanced browser automation with content anchors for intelligent LLM agents
- ✅ Full API parity with Python SDK
- ✅ Bug fixes and improvements
- ✅ Enhanced session management
- ✅ Improved error handling
- ✅ Code execution fully functional (Python, Bash)
- ✅ Browser automation complete (navigation, interaction, extraction)
- ✅ Comprehensive TypeScript support
- ✅ Error handling with specific error types
- ✅ Session management and automatic cleanup
- ✅ File upload capabilities
- ✅ Async execution support
- ✅ Event-driven browser sessions
- ✅ Modern build system with multiple output formats
The JavaScript SDK provides complete feature parity with the Python SDK and is ready for production use.