> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zenrows.com/llms.txt
> Use this file to discover all available pages before exploring further.

# The Response Object with the Node.js SDK

> Understand the Response object returned by every Zenrows Node.js SDK call.

Every method on `ZenRows` (`get` and `post`) resolves with a standard <a href="https://nodejs.org/api/globals.html#response" target="_blank" rel="noopener noreferrer nofollow">`Response`</a> object, the same one native `fetch` returns. The SDK doesn't wrap or transform it, so everything you already know about the Fetch API applies directly.

## Commonly used properties and methods

| Property / method | Returns | Use it when |
| - | - | - |
| `await response.text()` | Response body as a string | Reading HTML or plain text |
| `await response.json()` | Parsed JSON | The body is JSON (e.g. `json_response: true`) |
| `await response.arrayBuffer()` | Response body as raw bytes | Handling binary data (PDFs, screenshots, images) |
| `response.status` | HTTP status code, e.g. `200` | Checking exactly what happened |
| `response.ok` | `true` if `status` is 200-299 | Quick success check |
| `response.headers` | `Headers` object | Reading Zenrows monitoring headers |
| `response.url` | The final URL that was requested | Debugging what was actually sent |

<Warning>
  `response.text()` and `response.json()` are asynchronous, they return a `Promise` and must be awaited. This is different from libraries where the body is already available as a plain property.
</Warning>

<Tabs>
  <Tab title="Text / HTML">
    ```javascript theme={null} theme={"dark"}
    const response = await client.get(url);
    const html = await response.text();
    ```
  </Tab>

  <Tab title="Binary (PDF, screenshot)">
    ```javascript theme={null} theme={"dark"}
    const fs = require("fs/promises");

    const response = await client.get(url, { response_type: "pdf", js_render: true });
    const buffer = Buffer.from(await response.arrayBuffer());

    await fs.writeFile("page.pdf", buffer);
    ```

    <Tip>
      Use `response.arrayBuffer()` (not `response.text()`) when the target returns binary data. For example, a PDF from `response_type: "pdf"` or a screenshot.
    </Tip>
  </Tab>

  <Tab title="JSON">
    ```javascript theme={null} theme={"dark"}
    const response = await client.get(url, { json_response: true, js_render: true });
    const data = await response.json();
    ```
  </Tab>
</Tabs>

## Reading Zenrows-specific headers

Zenrows adds monitoring headers to every response, useful for debugging and tracking usage:

```javascript theme={null} theme={"dark"}
const response = await client.get(url);

console.log(response.headers.get("X-Request-Id"));          // unique ID for this request
console.log(response.headers.get("X-Request-Cost"));        // dollar cost of this request (e.g., 0.001)
console.log(response.headers.get("X-Request-Credits"));     // number of credits consumed by this request
console.log(response.headers.get("X-Key-Credits-Remaining")); // credits left before this key hits a credit cap (capped keys only)
console.log(response.headers.get("Concurrency-Remaining"));  // concurrency slots left on your plan
console.log(response.headers.get("Zr-Final-Url"));           // final URL after redirects
```

<Tip>
  If you ever contact Zenrows support about a failed request, include the `X-Request-Id` header value. It lets the team trace the exact request in the logs.
</Tip>

Headers coming from the target website itself are prefixed with `Zr-` to distinguish them from Zenrows' own headers. See the full list in the [Fetch setup guide](/fetch/setup#response-headers).

## Checking success before using the body

Because the SDK resolves with the response as-is rather than throwing on error status codes, always confirm the request succeeded first:

```javascript theme={null} theme={"dark"}
const response = await client.get(url);

if (response.ok) {
  const data = await response.text();
} else {
  console.log(`Request failed: ${response.status}`);
}
```

<Card title="Error Handling and Retries" icon="shield" href="/fetch/sdk/nodejs/error-handling-and-retries">
  More on this pattern, plus how to configure automatic retries.
</Card>

## Troubleshooting

* **`await response.json()` throws a `SyntaxError`**: The body isn't JSON. Confirm you requested `json_response: true` or that the target actually returns JSON before calling `.json()`.
* **Saved file (PDF, screenshot, image) is corrupted**: You wrote `response.text()` instead of `response.arrayBuffer()`, or forgot to wrap it in `Buffer.from(...)` before writing to disk.
* **Calling `response.text()` twice throws an error**: A `Response` body can only be read once. Store the result of the first call in a variable and reuse it instead of calling `.text()`/`.json()` again.
* **`response.url` doesn't match the URL you passed**: This is expected. It's the full URL sent to Zenrows' API (including your `apikey` and config as query parameters), not the target URL by itself.

## Pricing

The response itself doesn't add cost. Zenrows adds two headers to help you track usage:

* `X-Request-Cost`: the dollar cost of the request (e.g., `0.001`)
* `X-Request-Credits`: the number of credits consumed by the request

Both values are based on the config used:

| Configuration | Credits per request |
| - | - |
| Basic request | 1 |
| `js_render: true` | 5 |
| `premium_proxy: true` | 10 |
| `js_render: true` + `premium_proxy: true` | 25 |

See [Zenrows Pricing](/first-steps/pricing).

## FAQ (Frequently Asked Questions)

<AccordionGroup>
  <Accordion title="Is the response object specific to Zenrows?">
    No. It's the standard `Response` object from the Fetch API. Any Fetch API documentation or Stack Overflow answer about it applies here too.
  </Accordion>

  <Accordion title="How do I get the response as a JavaScript object?">
    Call `await response.json()` if the body is JSON. For example, when using `json_response: true` or `extract: 'auto'` on structured data.
  </Accordion>

  <Accordion title="Where do I find how much a request cost?">
    Check the response headers: `X-Request-Cost` gives you the dollar cost (e.g., `0.001`) and `X-Request-Credits` gives you the number of credits consumed. Read them with `response.headers.get("X-Request-Cost")` and `response.headers.get("X-Request-Credits")`.
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.