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

# Markdown Response

> Get scraped page content returned as clean Markdown instead of raw HTML using the `response_type=markdown` parameter.

The `response_type=markdown` parameter tells ZenRows to convert the scraped page's HTML into clean Markdown before returning the response. Instead of receiving raw HTML that you need to parse yourself, you get structured, readable content that's ready to process or display.

This is particularly useful for AI pipelines, content extraction workflows, and any use case where you need human-readable text with preserved structure (headings, lists, links, tables) without the noise of HTML tags.

<Warning>
  `response_type=markdown` cannot be combined with the `outputs` parameter. Use one or the other depending on whether you need structured data extraction or a full Markdown conversion of the page.
</Warning>

## How it works

ZenRows fetches the target page, renders it if needed, and converts the resulting HTML into Markdown. The conversion preserves the semantic structure of the page: headings map to `#` through `######`, lists remain as `-` items, links keep their text and URL, and tables are converted to Markdown table 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 Markdown response returns:

```markdown Markdown theme={null}
# Product Title

This is a great product that does many things.

- Feature 1
- Feature 2
- Feature 3
```

## Basic Usage

Add `response_type=markdown` 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": "markdown",
  }

  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: "markdown",
  },
  });

  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=markdown";
          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=markdown");
  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=markdown", 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=markdown")
  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=markdown"
  ```
</CodeGroup>

## When to use Markdown response

The Markdown response is the right choice when you need the full text content of a page with its structure preserved, but don't want to parse HTML yourself. It works well for:

* **AI and LLM pipelines**: feed scraped content directly into language models without pre-processing. Markdown is cleaner and more token-efficient than raw HTML.
* **Content extraction and archiving**: capture articles, documentation pages, or product descriptions in a portable, readable format.
* **Knowledge base ingestion**: convert web pages into Markdown for ingestion into vector databases, RAG pipelines, or internal wikis.
* **Developer tooling**: use Markdown output to power documentation crawlers, content diff tools, or search indexers.

<Note>If you only need specific data types from a page (like emails, links, or tables), use the `outputs` parameter instead. Markdown response converts the entire page, which may include content you don't need.</Note>

## Best practices

**Enable `js_render` for dynamic pages:** <br />
If the page loads content via JavaScript, combine `response_type=markdown` with `js_render=true`. Without it, the Markdown 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 conversion.

<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 />
The Markdown response converts the full page, including headers, footers, navigation menus, and sidebars. If you need only the main body content, consider post-processing the Markdown to strip boilerplate, or evaluate whether `css_extractor` with a targeted selector better fits your use case.

<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=markdown` is charged when the API returns a `200` status code, regardless of whether the Markdown output contains the content you expected. Test on a small set of URLs before running at scale.

## Troubleshooting

<AccordionGroup>
  <Accordion title="The Markdown 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 converting it. 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 includes a lot of navigation, ads, or boilerplate">
    The Markdown response converts the full HTML of the page, not just the main body. This is expected behavior. To target only a specific section of the page, use `css_extractor` with a selector pointing to the main content container (for example, `article` or `main`) instead of using `response_type=markdown`.
  </Accordion>

  <Accordion title="Tables are not converting correctly">
    Markdown table conversion works on standard HTML `table` elements. If the site uses `div`-based layouts to simulate tables, they won't convert cleanly. In that case, use the `outputs=tables` filter or `css_extractor` to target the relevant elements directly.
  </Accordion>

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

## Pricing

The `response_type=markdown` 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=markdown work with js_render?">
  Yes, you can combine `response_type=markdown` with `js_render=true` to render JavaScript before the conversion. This is recommended for any page that loads content dynamically.
</Accordion>

<Accordion title="Does it cost more credits to use response_type=markdown?">
  No, the `response_type=markdown` 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=markdown with the Scraping Browser?">
  No, `response_type=markdown` 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 and convert content using your own script logic.
</Accordion>

<Accordion title="What Markdown flavor does the conversion follow?">
  ZenRows converts to standard CommonMark-compatible Markdown. Most elements (headings, lists, bold, italic, links, code blocks, tables) are supported. Custom HTML components, embedded scripts, and non-semantic markup are stripped from the output.
</Accordion>

<Accordion title="Can I use response_type=markdown to feed content into an LLM?">
  Yes, and this is one of the most common use cases. Markdown is significantly more compact and cleaner than raw HTML, which reduces token usage and improves the quality of LLM outputs. ZenRows strips tags, scripts, and boilerplate during conversion, leaving structured prose that models can process directly.
</Accordion>
