npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

instavm

v0.8.3

Published

Official JavaScript SDK for InstaVM API

Readme

InstaVM JavaScript SDK

A comprehensive JavaScript/TypeScript client library for InstaVM's code execution and browser automation APIs.

Features

  • 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

Installation

npm install instavm

Quick Start

Code Execution (Cloud Mode)

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}`);
    } else if (error instanceof NetworkError) {
        console.log(`Network issue: ${error.message}`);
    }
} finally {
    await client.dispose();
}

Local Execution Mode

Run code execution against a local container (e.g., coderunner) instead of the cloud API:

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 navigation (browser.navigate())
  • ✅ Content extraction (browser.extractContent())

Local mode does NOT support (cloud-only features):

  • ❌ Session management (createSession(), closeSession(), getUsage())
  • ❌ File upload/download
  • ❌ Async execution
  • ❌ Browser session creation and complex interactions

File Upload

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);

File Download

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);

Error Handling

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`);
    } else if (error instanceof QuotaExceededError) {
        console.log("Usage quota exceeded");
    } else if (error instanceof SessionError) {
        console.log(`Session error: ${error.message}`);
    }
}

Async Execution

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}`);
console.log(`Stderr: ${taskResult.stderr}`);

Browser Automation

Basic Browser Usage

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();

Advanced Browser Interactions

// 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);

Browser Session Management

// 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}`);
    console.log(`Page title: ${result.title}`);
});

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');
}

Context Manager Pattern

// 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);

Mixed Code + Browser Automation

Combine code execution with browser automation for powerful workflows:

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

# Prepare search terms
search_terms = ["AI", "Machine Learning", "JavaScript"]
data = {"terms": search_terms, "timestamp": "2024-01-01"}
print(json.dumps(data))
`);

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(`
import json
data = ${JSON.stringify(results)}

# Analyze results
total_headlines = sum(len(item['headlines']) for item in data)
print(f"Collected {total_headlines} headlines across {len(data)} search terms")

# Find most common words
all_text = ' '.join([headline['text'] for item in data for headline in item['headlines']])
words = all_text.lower().split()
word_counts = {}
for word in words:
    if len(word) > 3:  # Filter short words
        word_counts[word] = word_counts.get(word, 0) + 1

# Top 10 words
top_words = sorted(word_counts.items(), key=lambda x: x[1], reverse=True)[:10]
print("Top words:", top_words)
`);

console.log(analysis.stdout);
await client.dispose();

Language Support

Python Code Execution

// Python with libraries
const result = await client.execute(`
import pandas as pd
import numpy as np

# Create sample data
data = pd.DataFrame({
    'numbers': np.random.randn(100),
    'categories': np.random.choice(['A', 'B', 'C'], 100)
})

# Basic statistics
print(f"Mean: {data['numbers'].mean():.2f}")
print(f"Std: {data['numbers'].std():.2f}")
print(f"Categories: {data['categories'].value_counts().to_dict()}")
`);

console.log(result.stdout);

Bash Commands

// System operations
const sysInfo = await client.execute(`
echo "System Information:"
echo "==================="
uname -a
echo
echo "Disk Usage:"
df -h
echo
echo "Memory Info:"
free -h
`, { language: 'bash' });

console.log(sysInfo.stdout);

Session Persistence

// 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

Session Status Check

// 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

Wait Conditions

// 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 
});

Screenshot Options

// 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

Element Extraction

// 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);

LLM-Friendly Content Extraction

// 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

Error Types

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');
    }
}

Retry Logic

The SDK includes automatic retry logic for:

  • Network errors (connection issues)
  • Rate limiting (with exponential backoff)
  • Server errors (5xx status codes)
// 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

InstaVM Client

class InstaVM {
    constructor(apiKey: string, options?: InstaVMOptions)

    // Code execution
    execute(command: string, options?: ExecuteOptions): Promise<ExecutionResult>
    executeAsync(command: string, options?: ExecuteOptions): Promise<AsyncExecutionResult>
    getTaskResult(taskId: string, pollInterval?: number, timeout?: number): Promise<TaskResult>

    // File operations
    upload(files: FileUpload[], options?: UploadOptions): Promise<UploadResult>
    download(filename: string, options?: DownloadOptions): Promise<DownloadResult>

    // Session management
    createSession(): Promise<string>
    closeSession(sessionId?: string): Promise<void>
    isSessionActive(sessionId?: string): Promise<boolean>
    getUsage(sessionId?: string): Promise<UsageStats>

    // Browser automation
    browser: BrowserManager

    // Properties
    readonly sessionId: string | null

    // Cleanup
    dispose(): Promise<void>
}

Configuration Options

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
}

Browser Manager

class BrowserManager {
    createSession(options?: BrowserSessionOptions): Promise<BrowserSession>
    listSessions(): Promise<BrowserSessionInfo[]>
    getSession(sessionId: string): Promise<BrowserSessionInfo>
    getLocalSession(sessionId: string): BrowserSession | undefined
    getLocalSessions(): BrowserSession[]
    closeAllSessions(): Promise<void>
    dispose(): Promise<void>
}

interface BrowserSessionOptions {
    viewportWidth?: number;   // Default: 1920
    viewportHeight?: number;  // Default: 1080
    userAgent?: string;       // Custom user agent
}

Browser Session

class BrowserSession extends EventEmitter {
    // Navigation
    navigate(url: string, options?: NavigateOptions): Promise<NavigationResult>
    
    // Interaction
    click(selector: string, options?: ClickOptions): Promise<void>
    type(selector: string, text: string, options?: TypeOptions): Promise<void>
    fill(selector: string, value: string, options?: FillOptions): Promise<void>
    scroll(options?: ScrollOptions): Promise<void>
    
    // Data extraction
    screenshot(options?: ScreenshotOptions): Promise<string>
    extractElements(selector: string, attributes?: string[]): Promise<ExtractedElement[]>
    extractContent(options?: ExtractContentOptions): Promise<ExtractedContent>

    // Utilities
    wait(condition: WaitCondition, timeout?: number): Promise<void>
    close(): Promise<void>
    
    // Properties
    readonly sessionId: string
    readonly isActive: boolean
    
    // Events: 'navigation', 'error', 'close'
}

Type Definitions

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

Resource Management

// 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<void>) {
    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);
});

Error Handling Strategy

// 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();
        }
    }
}

Performance Optimization

// 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:

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

Running Tests

# Install dependencies
npm install

# Run unit tests (no API key required)
npm run test:unit

# Run integration tests (requires API key)
INSTAVM_API_KEY=your_api_key npm run test:integration

# Run all tests
npm test

# Build the package
npm run build

# Type 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.

Contributing

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

Version 0.8.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

Version 0.4.0

  • 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
  • ✅ Parity with Python SDK v0.4.0 local mode features
  • ✅ Improved flexibility for on-premise deployments

Version 0.3.0

  • 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

Version 0.2.1

  • ✅ Bug fixes and improvements

Version 0.2.0

  • ✅ Enhanced session management
  • ✅ Improved error handling

Version 0.1.0

  • ✅ 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.