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

# Plain Text Response

> Get scraped page content returned as plain text, stripped of all HTML tags and formatting, using the `response_type=plaintext` parameter.

The `response_type=plaintext` parameter tells ZenRows to strip all HTML tags and formatting from the scraped page and return only the raw text content. You get the words on the page, nothing else.

This is useful when you don't need structure or markup. Just the text itself. It's a good fit for keyword analysis, sentiment analysis, full-text search indexing, or any pipeline where clean, unformatted content is easier to work with than HTML or Markdown.

<Warning>
  `response_type=plaintext` cannot be combined with the `outputs` parameter. Use one or the other depending on whether you need targeted data extraction or a plain text version of the full page.
</Warning>

## How it works

ZenRows fetches the target page, renders it if needed, and strips all HTML tags from the resulting content. The output preserves line breaks between block-level elements but removes all formatting: no headings, no bold, no links, no list syntax.

For example, given the following HTML:

```html HTML theme={null}
<h1>Product Title</h1>
<p>This is a great product that does many things.</p>
<ul>
    <li>Feature 1</li>
    <li>Feature 2</li>
    <li>Feature 3</li>
</ul>
```

The plain text response returns:

```text Plain text theme={null}
Product Title

This is a great product that does many things.

Feature 1
Feature 2
Feature 3
```

## Basic usage

Add `response_type=plaintext` to your request parameters:

<CodeGroup>
  ```python Python theme={null}
  import requests

  url = "https://www.scrapingcourse.com/ecommerce/"
  apikey = "YOUR_ZENROWS_API_KEY"

  params = {
      "url": url,
      "apikey": apikey,
      "response_type": "plaintext",
  }

  response = requests.get("https://api.zenrows.com/v1/", params=params)
  print(response.text)
  ```

  ```javascript Node.js theme={null}
  import axios from "axios";

  const url = "https://www.scrapingcourse.com/ecommerce/";
  const apikey = "YOUR_ZENROWS_API_KEY";

  const response = await axios.get("https://api.zenrows.com/v1/", {
    params: {
      url,
      apikey,
      response_type: "plaintext",
    },
  });

  console.log(response.data);
  ```

  ```java Java theme={null}
  import org.apache.hc.client5.http.fluent.Request;

  public class APIRequest {
      public static void main(final String... args) throws Exception {
          String apiUrl = "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.scrapingcourse.com%2Fecommerce%2F&response_type=plaintext";
          String response = Request.get(apiUrl)
                  .execute().returnContent().asString();
          System.out.println(response);
      }
  }
  ```

  ```php PHP theme={null}
  <?php
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.scrapingcourse.com%2Fecommerce%2F&response_type=plaintext");
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  $response = curl_exec($ch);
  echo $response . PHP_EOL;
  curl_close($ch);
  ?>
  ```

  ```go Go theme={null}
  package main

  import (
      "io"
      "log"
      "net/http"
  )

  func main() {
      client := &http.Client{}
      req, err := http.NewRequest("GET", "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.scrapingcourse.com%2Fecommerce%2F&response_type=plaintext", nil)
      if err != nil {
          log.Fatalln(err)
      }

      resp, err := client.Do(req)
      if err != nil {
          log.Fatalln(err)
      }
      defer resp.Body.Close()

      body, err := io.ReadAll(resp.Body)
      if err != nil {
          log.Fatalln(err)
      }

      log.Println(string(body))
  }
  ```

  ```ruby Ruby theme={null}
  require "faraday"

  url = URI.parse("https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.scrapingcourse.com%2Fecommerce%2F&response_type=plaintext")
  conn = Faraday.new()
  conn.options.timeout = 180
  res = conn.get(url, nil, nil)
  print(res.body)
  ```

  ```bash cURL theme={null}
  curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.scrapingcourse.com%2Fecommerce%2F&response_type=plaintext"
  ```
</CodeGroup>

## When to use plain text response

Plain text is the right choice when structure doesn't matter and you just need the words. It works well for:

* **NLP and text analysis**: run sentiment analysis, keyword extraction, or topic modeling directly on the output without pre-processing HTML.
* **Full-text search indexing**: feed clean text into search engines like Elasticsearch or Typesense without stripping tags in your pipeline.
* **LLM pipelines with minimal context**: when you want to reduce token usage further than Markdown allows and don't need headings or list structure preserved.
* **Content comparison and diffing**: compare page text across time or across URLs without formatting noise affecting the diff.
* **Readability and summarization tools**: pass clean prose to summarization models or readability scoring systems.

<Note>If you need the page structure preserved (headings, lists, links), use `response_type=markdown` instead. If you only need specific data types like emails or tables, use the `outputs` parameter.</Note>

## Best practices

**Enable `js_render` for dynamic pages:** <br />
If the page loads content via JavaScript, combine `response_type=plaintext` with `js_render=true`. Without it, the output will only reflect the initial HTML and may be missing key content.

**Use `wait` or `wait_for` when content loads after a delay:** <br />
For pages where content appears after a delay or user interaction, add `wait` (milliseconds) or `wait_for` (CSS selector) to ensure the full content is present before the text is extracted.

<Tip>Find more details on our [Wait Documentation](/universal-scraper-api/features/wait) or [Wait For Selector Documentation](/universal-scraper-api/features/wait-for).</Tip>

**Expect navigation and boilerplate in the output:** <br />
Plain text response strips tags but converts the full page, including headers, footers, navigation menus, and sidebars. If you need only the main body content, post-process the output to remove boilerplate, or evaluate whether `css_extractor` with a targeted selector fits your use case better.

<Tip>Find more details on our [CSS Extractor Documentation](/universal-scraper-api/features/css-extractor).</Tip>

**Credits are charged on successful responses:** <br />
A request using `response_type=plaintext` is charged when the API returns a `200` status code, regardless of whether the output contains the content you expected. Test on a small set of URLs before running at scale.

## Troubleshooting

<AccordionGroup>
  <Accordion title="The plain text output is missing most of the page content">
    The page likely renders its content via JavaScript. Add `js_render=true` to your request to ensure ZenRows renders the page fully before extracting the text. If content still appears incomplete, combine with `wait_for` targeting a CSS selector that's only present once the main content has loaded.
  </Accordion>

  <Accordion title="The output contains a lot of navigation, menu items, or footer text">
    Plain text response converts the full HTML of the page, not just the main body. This is expected behavior. To target only a specific section, use `css_extractor` with a selector pointing to the main content container (for example, `article` or `main`) and process the extracted HTML as needed.
  </Accordion>

  <Accordion title="I'm getting an error when combining response_type=plaintext with outputs">
    These two parameters are mutually exclusive. `response_type=plaintext` converts the entire page to plain text, while `outputs` performs targeted data extraction. You can only use one per request. Choose `outputs` when you need specific data types, and `response_type=plaintext` when you need clean, unformatted text from the full page.
  </Accordion>

  <Accordion title="The text output has inconsistent whitespace or blank lines">
    Plain text conversion preserves line breaks between block-level elements, which can result in multiple blank lines between sections depending on how the page is structured. Post-process the output with a simple whitespace normalization step in your code to clean it up before further processing.
  </Accordion>
</AccordionGroup>

## Pricing

The `response_type=plaintext` parameter is included at **no additional cost** with all ZenRows requests. You only pay extra for JavaScript Render and Premium Proxy when used.

<Tip>
  You can monitor your ZenRows usage in multiple ways to stay informed about your account activity and prevent unexpected overages.

  **Dashboard monitoring**: View real-time usage statistics, remaining requests, success rates, and request history on your [Analytics Page](https://app.zenrows.com/analytics/scraper-api). You can also set up usage alerts in your [notification settings](https://app.zenrows.com/account/notifications) to receive notifications when you approach your limits.

  **Programmatic monitoring**: For automated monitoring in your applications, call the `/v1/subscriptions/self/details` endpoint with your API key in the `X-API-Key` header. This returns real-time usage data that you can integrate into your monitoring systems. [Learn more about the usage endpoint](https://docs.zenrows.com/universal-scraper-api/features/other#plan-usage).

  **Response header monitoring**: Track your concurrency usage through response headers included with each request:

  * `Concurrency-Limit`: Your maximum concurrent requests
  * `Concurrency-Remaining`: Available concurrent request slots
  * `X-Request-Cost`: Cost of the current request
</Tip>

## FAQ (Frequently Asked Questions)

<Accordion title="Does response_type=plaintext work with js_render?">
  Yes, you can combine `response_type=plaintext` with `js_render=true` to render JavaScript before the text extraction. This is recommended for any page that loads content dynamically.
</Accordion>

<Accordion title="What is the difference between plaintext and markdown response types?">
  Both strip HTML tags, but `response_type=markdown` preserves the semantic structure of the page by converting headings, lists, links, and tables into Markdown syntax. `response_type=plaintext` removes all formatting entirely and returns only the raw text. Use Markdown when structure matters, and plain text when you just need the words.
</Accordion>

<Accordion title="Does it cost more credits to use response_type=plaintext?">
  No, the `response_type=plaintext` parameter does not add extra credit cost on its own. Credits are calculated based on the other parameters you use, such as `js_render` or `premium_proxy`, exactly as they would be for a standard request.
</Accordion>

<Accordion title="Can I use response_type=plaintext with the Scraping Browser?">
  No, `response_type=plaintext` is a parameter of the Universal Scraper API. It is not available in Scraping Browser (CDP/Playwright) sessions. In a Scraping Browser session, you control the page directly and can extract text content using standard browser APIs like `document.body.innerText`.
</Accordion>

<Accordion title="Can I use response_type=plaintext to feed content into an LLM?">
  Yes. Plain text is the most token-efficient format for LLM input since it contains no markup at all. It works well when the structure of the page is irrelevant to your task. If your LLM prompt benefits from knowing which text was a heading or a list item, use `response_type=markdown` instead.
</Accordion>
