<!--
hoody-browser Subskill (sdk)
Auto-generated by Hoody Skills Generator
Generated: 2026-05-06T20:10:09.267Z
Model: mimo-v2.5-pro
Mode: sdk


Tokens: 7523

DO NOT EDIT MANUALLY - Changes will be overwritten on next generation
-->

# hoody-browser Subskill

## Overview

**hoody-browser** provides headless Chrome browser automation accessible via HTTP REST API. It enables programmatic web browsing, screenshot capture, JavaScript execution, PDF generation, and browser state management — all without running a browser locally.

### When to Use

- **Web scraping**: Navigate pages, extract HTML/text content, handle dynamic JavaScript-rendered pages
- **Screenshot automation**: Capture full-page or viewport screenshots of any URL
- **PDF generation**: Convert web pages to PDF with custom formatting
- **Session management**: Maintain authenticated browser sessions with cookies
- **Testing & debugging**: Inspect console logs, network traffic, and page state
- **Automation pipelines**: Chain browser actions into multi-step workflows

### How It Fits Into Hoody

hoody-browser follows the Hoody Kit service philosophy: containerized, isolated, and accessible via HTTP. Each browser instance runs in its own process with configurable fingerprinting, proxy settings, and viewport options. Instances are identified by a `browser_id` you provide, enabling deterministic access across requests.

**Authentication**: Requests are authenticated through the Hoody Proxy routing layer using your Hoody API credentials. The SDK handles this automatically.

**Base URL pattern**:
```
https://{projectId}-{containerId}-browser-{serviceId}.{node}.containers.hoody.icu
```

**All paths are prefixed with `/api/v1/browser/`** — the SDK abstracts this away.

---

## Common Workflows

### 1. Start a Browser and Navigate to a Page

The most fundamental workflow: create an instance, navigate, and extract content.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

// Step 1: Create or retrieve a browser instance
const instance = await client.browser.instances.start({ browser_id: 'my-browser' })
// Returns: { browser_id, session_name, browser_name, browser_version, ... }

// Step 2: Navigate to a URL
const browseResult = await client.browser.interaction.browse('my-browser', {
  url: 'https://example.com'
})

// Step 3: Extract page content
const html = await client.browser.page.getHtml({ browser_id: 'my-browser' })
const text = await client.browser.page.getText({ browser_id: 'my-browser' })
```

### 2. Take a Screenshot

Capture visual state of any page with optional navigation.

```
// Navigate and capture in one call
const screenshot = await client.browser.interaction.takeScreenshot('my-browser', {
  url: 'https://example.com',
  fullPage: true,
  format: 'png'
})

// Or capture current page state (no URL)
const currentScreenshot = await client.browser.interaction.takeScreenshot({ browser_id: 'my-browser' })
```

### 3. Execute JavaScript

Run arbitrary JS in the page context for dynamic interaction or data extraction.

```
// GET method — script as query parameter
const result = await client.browser.interaction.evalGet('my-browser', {
  script: 'document.title'
})

// POST method — script in request body (better for complex scripts)
const result2 = await client.browser.interaction.evalPost('my-browser', {
  script: `
    const items = document.querySelectorAll('.product');
    return Array.from(items).map(el => ({
      name: el.querySelector('.title')?.textContent,
      price: el.querySelector('.price')?.textContent
    }));
  `
})
```

### 4. Manage Cookies

Persist authentication state across requests.

```
// Set cookies for authenticated session
await client.browser.cookies.set('my-browser', {
  cookies: [
    {
      name: 'session_id',
      value: 'abc123',
      url: 'https://example.com'
    }
  ]
})

// Retrieve cookies (optionally filtered by URL)
const cookies = await client.browser.cookies.get('my-browser', {
  url: 'https://example.com'
})

// Clear all cookies
await client.browser.cookies.clear({ browser_id: 'my-browser' })
```

### 5. Generate PDF

Convert any page to a formatted PDF document.

```
const pdf = await client.browser.page.exportPdf('my-browser', {
  url: 'https://example.com/report',
  format: 'A4',
  landscape: false,
  printBackground: true,
  margin: '1cm'
})
```

### 6. Multi-Tab Management

Work with multiple tabs within a single browser instance.

```
// Open a new tab by navigating
await client.browser.interaction.browse('my-browser', {
  url: 'https://example.com/page1',
  active: true
})

// Open another tab
await client.browser.interaction.browse('my-browser', {
  url: 'https://example.com/page2',
  active: false
})

// List all tabs
const tabs = await client.browser.tabs.listTabs('my-browser')

// Close a specific tab
await client.browser.introspection.closeTab('my-browser', {
  tabId: 1
})
```

### 7. Inspect Browser State

Get detailed metadata about a running instance.

```
const metadata = await client.browser.introspection.getMetadata({ browser_id: 'my-browser' })
// Returns: browser_id, session_name, browser_name, browser_version, user_agent, os, viewport, ...

const devtools = await client.browser.introspection.getDevtoolsUrl({ browser_id: 'my-browser' })
// Returns: websocket URL and HTTP discovery URL for Chrome DevTools
```

### 8. Debug with Console and Network Logs

Capture browser-side errors and network activity.

```
// Get console messages (last 500 entries)
const consoleLogs = await client.browser.debugging.getConsoleLogs('my-browser', {
  type: 'error'
})

// Get network requests (last 500 entries)
const networkLogs = await client.browser.debugging.getNetworkLogs({ browser_id: 'my-browser' })
```

### 9. Query and Clear Browsing History

```
// Query history with filters
const history = await client.browser.history.list({
  browser_id: 'my-browser',
  domain: 'example.com',
  limit: 50,
  offset: 0
})

// Delete all history for a browser
await client.browser.history.clear({
  browser_id: 'my-browser'
})
```

### 10. Stop and Cleanup

Properly release resources when done.

```
// Stop a specific instance
await client.browser.instances.stop({ browser_id: 'my-browser' })

// Or shutdown (terminates the browser process)
await client.browser.introspection.shutdown({ browser_id: 'my-browser' })
```

---

## Advanced Operations

### Full Scraping Pipeline with Error Recovery

A robust workflow that handles navigation failures, retries, and extracts structured data.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

async function scrapeWithRetry(urls: string[], maxRetries = 3) {
  // Step 1: Start browser with custom configuration
  await client.browser.instances.start('scraper', {
    userAgent: 'Mozilla/5.0 (compatible; HoodyBot/1.0)',
    viewport: '1920x1080',
    stealth: true
  })

  const results: Array<{ url: string; title: string; text: string }> = []

  for (const url of urls) {
    let attempt = 0
    while (attempt < maxRetries) {
      try {
        // Step 2: Navigate
        await client.browser.interaction.browse('scraper', { url })

        // Step 3: Wait for content via JS evaluation
        await client.browser.interaction.evalGet('scraper', {
          script: 'document.readyState'
        })

        // Step 4: Extract structured data
        const title = await client.browser.interaction.evalGet('scraper', {
          script: 'document.title'
        })
        const text = await client.browser.page.getText({ browser_id: 'scraper' })

        results.push({ url, title, text })
        break
      } catch (error) {
        attempt++
        if (attempt >= maxRetries) {
          console.error(`Failed after ${maxRetries} attempts: ${url}`)
        }
        // Restart browser on persistent failures
        if (attempt === 2) {
          await client.browser.instances.restart({ browser_id: 'scraper' })
        }
      }
    }
  }

  // Step 5: Cleanup
  await client.browser.instances.stop({ browser_id: 'scraper' })
  return results
}
```

### Authenticated Session Workflow

Maintain login state across multiple page navigations.

```
async function authenticatedScrape(loginUrl: string, targetUrl: string) {
  // Start browser
  await client.browser.instances.start({ browser_id: 'auth-browser' })

  // Navigate to login page
  await client.browser.interaction.browse('auth-browser', { url: loginUrl })

  // Fill and submit login form via JS
  await client.browser.interaction.evalPost('auth-browser', {
    script: `
      document.querySelector('#username').value = 'user';
      document.querySelector('#password').value = 'pass';
      document.querySelector('#login-form').submit();
    `
  })

  // Wait for navigation by checking URL
  await client.browser.interaction.evalGet('auth-browser', {
    script: 'window.location.href'
  })

  // Cookies are now set — navigate to protected page
  await client.browser.interaction.browse('auth-browser', { url: targetUrl })

  // Extract authenticated content
  const content = await client.browser.page.getText({ browser_id: 'auth-browser' })

  // Optionally persist cookies for reuse
  const cookies = await client.browser.cookies.get({ browser_id: 'auth-browser' })

  await client.browser.instances.stop({ browser_id: 'auth-browser' })
  return { content, cookies }
}
```

### PDF Report Generation Pipeline

Generate multiple formatted PDFs from a list of URLs.

```
async function generateReports(urls: string[]) {
  await client.browser.instances.start({ browser_id: 'pdf-gen' })

  const pdfs: Array<{ url: string; pdf: Buffer }> = []

  for (const url of urls) {
    const pdf = await client.browser.page.exportPdf('pdf-gen', {
      url,
      format: 'A4',
      landscape: true,
      printBackground: true,
      margin: '2cm'
    })
    pdfs.push({ url, pdf })
  }

  await client.browser.instances.stop({ browser_id: 'pdf-gen' })
  return pdfs
}
```

### Performance Considerations

- **Instance reuse**: Start one browser instance and reuse it across multiple navigations rather than starting/stopping for each URL
- **Tab parallelism**: Use multiple tabs within one instance for moderate parallelism; use separate instances for heavy parallel workloads
- **Cookie persistence**: Set cookies before navigation to avoid redirect overhead on authenticated sites
- **History management**: Periodically clear history with `DELETE /history` to prevent storage bloat on long-running instances
- **Resource cleanup**: Always call `stop` or `shutdown` when finished — orphaned instances consume memory
- **Health checks**: Use `GET /api/v1/browser/health` to verify service availability before starting workflows

---

## Quick Reference

### Essential Endpoints

| Operation | SDK Method | HTTP |
|-----------|-----------|------|
| Start instance | `client.browser.instances.start(browser_id)` | GET /api/v1/browser/start |
| Stop instance | `client.browser.instances.stop(browser_id)` | GET /api/v1/browser/stop |
| Navigate | `client.browser.interaction.browse(browser_id, { url })` | GET /api/v1/browser/browse |
| Screenshot | `client.browser.interaction.takeScreenshot(browser_id, { url })` | GET /api/v1/browser/screenshot |
| Execute JS | `client.browser.interaction.evalGet(browser_id, { script })` | GET /api/v1/browser/eval |
| Get HTML | `client.browser.page.getHtml(browser_id)` | GET /api/v1/browser/html |
| Get text | `client.browser.page.getText(browser_id)` | GET /api/v1/browser/text |
| Export PDF | `client.browser.page.exportPdf(browser_id, { url })` | GET /api/v1/browser/pdf |
| Get cookies | `client.browser.cookies.get(browser_id)` | GET /api/v1/browser/cookies |
| Set cookies | `client.browser.cookies.set(browser_id, { cookies })` | POST /api/v1/browser/cookies |
| List tabs | `client.browser.tabs.listTabs(browser_id)` | GET /api/v1/browser/tabs |
| Get metadata | `client.browser.introspection.getMetadata(browser_id)` | GET /api/v1/browser/metadata |
| Console logs | `client.browser.debugging.getConsoleLogs(browser_id)` | GET /api/v1/browser/console |
| Network logs | `client.browser.debugging.getNetworkLogs(browser_id)` | GET /api/v1/browser/network |
| Health check | `client.browser.health.check()` | GET /api/v1/browser/api/v1/browser/health |

### Required Parameters

Every browser operation requires `browser_id` as the first argument. This is a string you define — it identifies your browser instance across all requests.

### Typical Response Formats

**Instance metadata** includes: `browser_id`, `session_name`, `browser_name`, `browser_version`, `user_agent`, `os`, `viewport`, `geolocation`.

**Browse result** includes: navigation status, final URL, page title.

**Health check** returns a 9-field standardized contract with service status, uptime, and version information.