# How camofox-browser Snapshot Screenshots Include Base64 PNG Images

> Learn how jo inc camofox-browser embeds Base64 PNG screenshots directly into JSON responses using the includeScreenshot query parameter for easy integration.

- Repository: [jo/camofox-browser](https://github.com/jo-inc/camofox-browser)
- Tags: how-to-guide
- Published: 2026-04-15

---

**When the `includeScreenshot=true` query parameter is passed to the `/snapshot` endpoint, camofox-browser captures a PNG via Playwright, converts the binary buffer to Base64 using `pngBuffer.toString('base64')`, and embeds it within the JSON response as a structured object containing `mimeType` and `data` fields.**

The camofox-browser repository (jo-inc/camofox-browser) provides a browser automation server that generates accessible DOM snapshots alongside optional visual screenshots. Understanding how camofox-browser snapshot screenshots include base64 PNG images is essential for integrating visual verification into LLM toolchains and automated testing workflows.

## The `/snapshot` Endpoint and Screenshot Activation

The `/snapshot` route and its cached-offset variant support optional screenshot generation through a query string parameter. When the request includes **`includeScreenshot=true`**, the handler triggers a visual capture of the current page state.

This functionality is implemented consistently across three distinct code paths in [`server.js`](https://github.com/jo-inc/camofox-browser/blob/main/server.js):

1. **Cached-offset path** (lines 1876-1880): Retrieves a previously computed snapshot window and attaches the screenshot when requested.
2. **Google SERP fast-path** (lines 1823-1826): Processes Google search results pages, building the snapshot before optionally appending the screenshot.
3. **Normal ARIA snapshot path** (lines 1829-1832): Generates an accessibility tree snapshot and conditionally includes the Base64 PNG image.

## Base64 Encoding Implementation in [`server.js`](https://github.com/jo-inc/camofox-browser/blob/main/server.js)

The conversion from binary PNG to Base64 string occurs through a two-step process in the route handlers. First, Playwright captures the screenshot using:

```javascript
await tabState.page.screenshot({ type: 'png' })

```

Then, the resulting buffer undergoes encoding:

```javascript
const base64String = pngBuffer.toString('base64')

```

The handler constructs the response object by adding a **`screenshot`** field to the JSON payload. This field contains an object with **`data`** (the Base64 string) and **`mimeType`** set to `'image/png'`.

The same encoding logic applies across all three snapshot paths in [`server.js`](https://github.com/jo-inc/camofox-browser/blob/main/server.js), ensuring consistent behavior whether processing cached offsets, Google SERP pages, or standard ARIA-based snapshots.

## Requesting and Decoding Screenshot Data

Clients can request a snapshot with an embedded screenshot using HTTP query parameters or programmatic client methods.

### HTTP Request Example

Use the `includeScreenshot=true` query parameter when calling the `/snapshot` endpoint:

```bash
curl -G "http://localhost:9377/snapshot" \
  -d "userId=myUser" \
  -d "targetId=abc123" \
  -d "includeScreenshot=true" \
  -H "Accept: application/json"

```

The JSON response structure includes the Base64-encoded image:

```json
{
  "url": "https://example.com",
  "snapshot": "...",
  "refsCount": 42,
  "screenshot": {
    "mimeType": "image/png",
    "data": "iVBORw0KGgoAAAANSUhEUgAA..."
  }
}

```

### Decoding the Base64 PNG

To convert the Base64 string back to binary data in Node.js:

```javascript
const base64Data = snapshot.screenshot.data;
const pngBuffer = Buffer.from(base64Data, 'base64');

// Verify PNG magic bytes (optional validation)
if (pngBuffer[0] === 0x89 && pngBuffer[1] === 0x50 &&
    pngBuffer[2] === 0x4E && pngBuffer[3] === 0x47) {
  console.log('Valid PNG image');
}

```

## Why Base64 Encoding Is Used

Base64 encoding serves two primary technical purposes in the camofox-browser architecture. **JSON cannot transport raw binary data**, so encoding the PNG buffer to Base64 preserves the image data within a text-safe format that maintains JSON payload validity.

Additionally, the LLM toolchain expects image data in a structured `{ mimeType, data }` format, mirroring the "image block" convention used by OpenClaw and similar systems. This standardization allows seamless integration with language model interfaces that consume both textual snapshots and visual screenshots.

## Testing and Validation

The end-to-end test suite in **[`tests/e2e/snapshotScreenshot.test.js`](https://github.com/jo-inc/camofox-browser/blob/main/tests/e2e/snapshotScreenshot.test.js)** validates the Base64 encoding implementation through several assertions:

- The `screenshot` property exists and contains a non-empty Base64 string when `includeScreenshot=true`.
- Decoded data begins with the PNG magic bytes `0x89 0x50 0x4E 0x47`.
- ARIA snapshot content remains unchanged regardless of screenshot inclusion.

Separate unit tests in [`tests/unit/screenshotToolResult.test.js`](https://github.com/jo-inc/camofox-browser/blob/main/tests/unit/screenshotToolResult.test.js) cover the `/tabs/:tabId/screenshot` endpoint, which returns raw binary PNG data rather than Base64-encoded JSON.

## Summary

- **Three implementation paths** in [`server.js`](https://github.com/jo-inc/camofox-browser/blob/main/server.js) (lines 1823-1880) handle screenshot generation for cached offsets, Google SERP pages, and standard ARIA snapshots.
- **Playwright capture and Node.js encoding**: The `page.screenshot({ type: 'png' })` method generates the image, while `buffer.toString('base64')` handles the encoding.
- **Structured response format**: Screenshots appear as `{ mimeType: 'image/png', data: <base64> }` objects within the JSON response.
- **Validation via magic bytes**: The test suite confirms PNG validity by checking for the `0x89 0x50 0x4E 0x47` header signature after Base64 decoding.

## Frequently Asked Questions

### How do I request a Base64-encoded screenshot from camofox-browser?

Append `includeScreenshot=true` as a query parameter to the `/snapshot` endpoint request. The JSON response will contain a `screenshot` object with `mimeType` set to `'image/png'` and `data` containing the Base64 string.

### What does the screenshot object structure look like in the JSON response?

The screenshot field contains an object with two properties: `mimeType` (always `'image/png'`) and `data` (the Base64-encoded PNG string). This structure allows clients to identify the image format and decode the binary data accordingly.

### How does the test suite verify the screenshot is a valid PNG?

Tests in [`tests/e2e/snapshotScreenshot.test.js`](https://github.com/jo-inc/camofox-browser/blob/main/tests/e2e/snapshotScreenshot.test.js) decode the Base64 string and verify the resulting buffer starts with the PNG magic bytes `0x89 0x50 0x4E 0x47`. This confirms the data represents a valid PNG image rather than corrupted or empty content.

### Why does the API use Base64 encoding instead of returning raw binary image data?

JSON responses cannot contain raw binary data without corruption or encoding issues. Base64 encoding ensures the image data remains intact within the JSON payload while remaining compatible with LLM toolchains that expect structured `{ mimeType, data }` image blocks.