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

# Troubleshooting Partial or Empty Responses

> Troubleshoot empty or partial scraping responses from JavaScript-rendered pages. Covers wait parameters, AJAX handling, and ZenRows fixes.

Sometimes, your requests may return empty or incomplete content. This is typically due to how modern websites load content dynamically using JavaScript or AJAX (XHR) calls. By default, ZenRows returns the HTML content once the DOM is initially loaded, which might not include content populated by JavaScript.

This guide provides diagnostic steps, common scenarios, and parameter configurations to help you resolve these issues and get complete, usable responses.

<Tip>These troubleshooting steps are applicable across all ZenRows features, including `screenshot`, `outputs`, `json_response`, and others.</Tip>

## Why Does This Happen?

Even if a page visually "loads," its content might still be missing because:

* The content is rendered by **JavaScript** after the DOM loads.
* The actual data is fetched via **XHR (AJAX) requests**.
* The page relies on **user interaction** or **delays** to render content.
* **Anti-bot measures** may serve minimal or obfuscated content.

## Quick Decision Tree

```plaintext theme={null}
ERROR
  ↓
Is js_render enabled?
  ├─ No → Enable `js_render`
  └─ Yes
       ↓
   Is content dynamic (loaded after a delay or via JS)?
       ├─ Yes → Use `wait` or `wait_for`
       └─ No
            ↓
     Is content loaded via XHR?
            ├─ Yes → Use `json_response`
            └─ No → Enable screenshot to visually debug
                ↓
        Does the page require user interaction?
                ├─ Yes → Use `js_instructions`
                └─ No → Content may be static or blocked

```

## Parameter Reference

| Parameter                                                           | Description                                                               | Required When                                   | Type    |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------- | ------- |
| [js\_render](/universal-scraper-api/features/js-rendering)          | Enables JavaScript rendering in a headless browser                        | Site loads content via JS                       | Boolean |
| [wait](/universal-scraper-api/features/wait)                        | Waits for a specified time in milliseconds before returning the response  | Site loads slowly                               | Integer |
| [wait\_for](/universal-scraper-api/features/wait-for)               | Waits for a specific CSS selector to be present                           | Site depends on dynamic elements                | String  |
| [json\_response](/universal-scraper-api/features/json-response)     | Extracts data from XHR/Fetch calls loaded during page render              | Site uses API calls for content                 | Boolean |
| [js\_instructions](/universal-scraper-api/features/js-instructions) | Performs custom user interactions (clicks, scrolls, etc.)                 | Site requires interaction to reveal content     | Array   |
| [premium\_proxy](/universal-scraper-api/features/premium-proxy)     | Uses residential proxies to avoid detection and access restricted content | Site blocks datacenter IPs or has bot detection | Boolean |

## Recommended Steps

### 1. Enable JavaScript Rendering

If the target website relies on JavaScript to display content, enable `js_render`. This ensures that ZenRows runs JavaScript in a headless browser to render the page fully.

<CodeGroup>
  ```python Python theme={null}
  params = {
      'url': url,
      'apikey': apikey,
  	'js_render': 'true',
  }
  ```

  ```bash cURL theme={null}
  curl "<...>&js_render=true"
  ```
</CodeGroup>

This parameter is required when using other advanced features such as `wait`, `wait_for`, `screenshot`, `json_response`, `outputs`, and others.

### 2. Use Wait Parameters

Some websites load content after a delay. Use the `wait` parameter to introduce a fixed delay or `wait_for` to wait for a specific CSS selector to appear.

#### Example with `wait`

<CodeGroup>
  ```python Python theme={null}
  params = {
      'url': url,
      'apikey': apikey,
  	'js_render': 'true',
  	'wait': '15000', # Waits for 15 seconds
  }
  ```

  ```bash cURL theme={null}
  curl "<...>&js_render=true&wait=15000"
  ```
</CodeGroup>

#### Example with `wait_for`

<CodeGroup>
  ```python Python theme={null}
  params = {
      'url': url,
      'apikey': apikey,
  	'js_render': 'true',
  	'wait_for': '.content-loaded', # Waits for the specified CSS selector
  }
  ```

  ```bash cURL theme={null}
  curl "<...>&js_render=true&wait_for=.content-loaded"
  ```
</CodeGroup>

<Tip>`wait_for` will cause the request to fail if the selector is not found. Use browser DevTools to find reliable CSS selectors on your target site.</Tip>

### 3. Use `json_response` for XHR-based Pages

If the data you're trying to scrape is loaded via JavaScript through AJAX calls, you can use the `json_response` parameter to access the response of those internal XHR requests.

<CodeGroup>
  ```python Python theme={null}
  params = {
      'url': url,
      'apikey': apikey,
  	'js_render': 'true',
  	'wait_for': '.selector',
  	'json_response': 'true',
  }
  ```

  ```bash cURL theme={null}
  curl "<...>&js_render=true&wait_for=.selector&json_response=true"
  ```
</CodeGroup>

<Tip>Combine `json_response` with `wait` or `wait_for` to ensure all background requests have completed before data is captured.</Tip>

### 4. Use Screenshot for Debugging

To understand what ZenRows actually "sees", enable the `screenshot` parameter. This can help determine whether content is missing due to rendering delays or protections.

<CodeGroup>
  ```python Python theme={null}
  params = {
      'url': url,
      'apikey': apikey,
  	'js_render': 'true',
  	'wait_for': '.selector',
  	'screenshot': 'true',
  }   
  ```

  ```bash cURL theme={null}
  curl "<...>&js_render=true&wait_for=.selector&screenshot=true"
  ```
</CodeGroup>

This feature provides a rendered image of the page after all scripts have run and delays have passed.

### 5. Use js\_instructions for Interactive Pages

If the page requires user interaction to load the content (like clicking a button, scrolling, or inputting text), use the `js_instructions` parameter. This allows you to simulate actions in the browser before the content is captured.

Example:

<CodeGroup>
  ```python Python theme={null}
  params = {
      'url': url,
      'apikey': apikey,
  	'js_render': 'true',
  	'js_instructions': """[
          {"click":".selector"},
          {"wait":500},
          {"fill":[".input","value"]},
          {"wait_for":".slow_selector"}
      ]""",
  } 
  ```

  ```bash cURL theme={null}
  curl "<...>&js_render=true&js_instructions=%255B%257B%2522click%2522%253A%2522.selector%2522%257D%252C%257B%2522wait%2522%253A500%257D%252C%257B%2522fill%2522%253A%255B%2522.input%2522%252C%2522value%2522%255D%257D%252C%257B%2522wait_for%2522%253A%2522.slow_selector%2522%257D%255D"
  ```
</CodeGroup>

When using `js_instructions`, each instruction can have an optional `wait_for` step. If the selector is not found, ZenRows will attempt the next instruction after a short delay.

## Mixing Steps for Advanced Debugging

You can combine multiple steps for complex scenarios. For example:

* Use `js_instructions` to simulate user interactions, followed by `json_response` to capture XHR data.
* Enable `screenshot` alongside `wait_for` to visually confirm dynamic content.

Example:

<CodeGroup>
  ```python Python theme={null}
  params = {
      'url': url,
      'apikey': apikey,
  	'js_render': 'true',
  	'js_instructions': """[
          {"click":".selector"},
          {"wait":500},
          {"fill":[".input","value"]},
          {"wait_for":".slow_selector"}
      ]""",
      'json_response': 'true',
  } 
  ```

  ```bash cURL theme={null}
  curl "<...>&js_render=true&js_instructions=%255B%257B%2522click%2522%253A%2522.selector%2522%257D%252C%257B%2522wait%2522%253A500%257D%252C%257B%2522fill%2522%253A%255B%2522.input%2522%252C%2522value%2522%255D%257D%252C%257B%2522wait_for%2522%253A%2522.slow_selector%2522%257D%255D&json_response=true"
  ```
</CodeGroup>

## Summary Table

| Scenario                             | Recommended Parameters                       | Notes                                                             |
| ------------------------------------ | -------------------------------------------- | ----------------------------------------------------------------- |
| Empty or partially loaded pages      | `js_render=true`                             | Ensures JavaScript runs to render dynamic content                 |
| Content loads slowly                 | `wait=5000` or `wait_for=.selector`          | Allows time for content to appear or specific element to load     |
| Page requires user interaction       | `js_instructions=[{"click":".selector"}...]` | Simulates user actions like dismissing modals or clicking buttons |
| Data comes from background requests  | `json_response=true` + `wait` or `wait_for`  | Captures XHR/Fetch data loaded after DOM is ready                 |
| Complex sites with strong protection | `premium_proxy=true` + `js_render=true`      | Mimics real browser with rotating residential IPs                 |

## Still Stuck?

If you're still getting empty or partial responses after following the steps above:

1. Double-check your CSS selectors in DevTools
2. Use a screenshot to confirm what ZenRows is rendering
3. Reach out to support at [success@zenrows.com](mailto:success@zenrows.com) with:
   * Your full request URL.
   * Parameters used.
   * Expected vs actual response.
   * What you've already tested.
   * Any other useful information, such as specific errors or observations.

Our team will help you optimize your request for better results.
