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

# Other Outputs

> Use ZenRows output filters to extract specific data types like links, images, and email addresses from scraped pages in structured JSON format.

## Output Filters

The `outputs` parameter lets you specify which data types to extract from the scraped HTML. This allows you to efficiently retrieve only the data types you're interested in, reducing processing time and focusing on the most relevant information.

The parameter accepts a comma-separated list of filter names and returns the results in a structured JSON format.

<Tip>Use `outputs=*` to retrieve all available data types.</Tip>

Here's an example of how to use the `outputs` parameter:

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

  url = 'https://www.scrapingcourse.com/ecommerce/'
  apikey = 'YOUR_ZENROWS_API_KEY'
  params = {
      'url': url,
      'apikey': apikey,
  	'outputs': 'emails,headings,menus',
  }
  response = requests.get('https://api.zenrows.com/v1/', params=params)
  print(response.text)
  ```

  ```javascript Node.js theme={null}
  // npm install axios
  const axios = require('axios');

  const url = 'https://www.scrapingcourse.com/ecommerce/';
  const apikey = 'YOUR_ZENROWS_API_KEY';
  axios({
  	url: 'https://api.zenrows.com/v1/',
  	method: 'GET',
  	params: {
  		'url': url,
  		'apikey': apikey,
  		'outputs': 'emails,headings,menus',
  	},
  })
      .then(response => console.log(response.data))
      .catch(error => console.log(error));
  ```

  ```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&outputs=emails,headings,menus";
          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&outputs=emails,headings,menus');
  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&outputs=emails,headings,menus", 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}
  # gem install faraday
  require 'faraday'

  url = URI.parse('https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.scrapingcourse.com%2Fecommerce%2F&outputs=emails,headings,menus')
  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&outputs=emails,headings,menus"
  ```
</CodeGroup>

Supported Filters and Examples:

### Emails

Extracts email addresses using CSS selectors and regular expressions. This includes standard email formats like `example@example.com` and obfuscated versions like `example[at]example.com`.

Example: `outputs=emails`

```json output theme={null}
{
  "emails": [
    "example@example.com",
    "info@website.com",
    "contact[at]domain.com",
    "support at support dot com"
  ]
}
```

### Phone Numbers

Extracts phone numbers using CSS selectors and regular expressions, focusing on links with `tel:` protocol.

Example: `outputs=phone_numbers`

```json output theme={null}
{
  "phone_numbers": [
    "+1-800-555-5555",
    "(123) 456-7890",
    "+44 20 7946 0958"
  ]
}
```

### Headings

Extracts heading text from HTML elements `h1` through `h6`.

Example: `outputs=headings`

```json output theme={null}
{
  "headings": [
    "Welcome to Our Website",
    "Our Services",
    "Contact Us",
    "FAQ"
  ]
}
```

### Images

Extracts image sources from `img` tags. Only the `src` attribute is returned.

Example: `outputs=images`

```json output theme={null}
{
  "images": [
    "https://example.com/image1.jpg",
    "https://example.com/image2.png"
  ]
}
```

### Audios

Extracts audio sources from `source` elements inside audio tags. Only the `src` attribute is returned.

Example: `outputs=audios`

```json output theme={null}
{
  "audios": [
    "https://example.com/audio1.mp3",
    "https://example.com/audio2.wav"
  ]
}
```

### Videos

Extracts video sources from `source` elements inside video tags. Only the `src` attribute is returned.

Example: `outputs=videos`

```json output theme={null}
{
  "videos": [
    "https://example.com/video1.mp4",
    "https://example.com/video2.webm"
  ]
}
```

### Links

Extracts URLs from `a` tags. Only the `href` attribute is returned.

Example: `outputs=links`

```json output theme={null}
{
  "links": [
    "https://example.com/page1",
    "https://example.com/page2"
  ]
}
```

### Menus

Extracts menu items from `li` elements inside `menu` tags.

Example: `outputs=menus`

```json output theme={null}
{
  "menus": [
    "Home",
    "About Us",
    "Services",
    "Contact"
  ]
}
```

### Hashtags

Extracts hashtags using regular expressions, matching typical hashtag formats like `#example`.

Example: `outputs=hashtags`

```json output theme={null}
{
  "hashtags": [
    "#vacation",
    "#summer2024",
    "#travel"
  ]
}
```

### Metadata

Extracts meta-information from `meta` tags inside the `head` section. Returns `name` and `content` attributes in the format `name: content`.

Example: `outputs=metadata`

```json output theme={null}
{
  "metadata": [
    "description: This is an example webpage.",
    "keywords: example, demo, website",
    "author: John Doe"
  ]
}
```

### Tables

Extracts data from `table` elements and returns the table data in JSON format, including dimensions, headings, and content.

Example: `outputs=tables`

```json output theme={null}
{
  "dimensions": {
    "rows": 4,
    "columns": 4,
    "heading": true
  },
  "heading": ["A", "B", "C", "D"],
  "content": [
    {"A": "1", "B": "1", "C": "1", "D": "1"},
    {"A": "2", "B": "2", "C": "2", "D": "2"},
    {"A": "3", "B": "3", "C": "3", "D": "3"},
    {"A": "4", "B": "4", "C": "4", "D": "4"}
  ]
}
```

### Favicon

Extracts the favicon URL from the `link` element in the `head` section of the HTML.

Example: `outputs=favicon`

```json output theme={null}
{
  "favicon": "https://example.com/favicon.ico"
}
```

## Markdown Response

By adding `response_type=markdown` to the request parameters, the ZenRows API will return the content in a Markdown format, making it easier to read and work with, especially if you are more comfortable with Markdown than HTML.

It can be beneficial if you prefer working with Markdown for its simplicity and readability.

<Warning>You can't use the Markdown Response in conjunction with other outputs</Warning>

Add `response_type=markdown` to the request:

<CodeGroup>
  ```python Python theme={null}
  # pip install requests
  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}
  // npm install axios
  const axios = require('axios');

  const url = 'https://www.scrapingcourse.com/ecommerce/';
  const apikey = 'YOUR_ZENROWS_API_KEY';
  axios({
  	url: 'https://api.zenrows.com/v1/',
  	method: 'GET',
  	params: {
  		'url': url,
  		'apikey': apikey,
  		'response_type': 'markdown',
  	},
  })
      .then(response => console.log(response.data))
      .catch(error => console.log(error));
  ```

  ```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}
  # gem install faraday
  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>

Let's say the HTML content of the ScrapingCourse product page includes a product title, a description, and a list of features. In HTML, it might look something like this:

```bash 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>
```

When you enable the Markdown response feature, ZenRows Universal Scraper API will convert this HTML content into Markdown like this:

```bash theme={null}
# Product Title

This is a great product that does many things.

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

## Plain Text Response

The `plaintext` feature is an output option that returns the scraped content as plain text instead of HTML or Markdown.

This feature can be helpful when you want a clean, unformatted version of the content without any HTML tags or Markdown formatting. It simplifies the content extraction process and makes processing or analyzing the text easier.

<Warning>You can't use the Plain Text Response in conjunction with other outputs</Warning>

Add `response_type=plaintext` to the request:

<CodeGroup>
  ```python Python theme={null}
  # pip install requests
  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}
  // npm install axios
  const axios = require('axios');

  const url = 'https://www.scrapingcourse.com/ecommerce/';
  const apikey = 'YOUR_ZENROWS_API_KEY';
  axios({
  	url: 'https://api.zenrows.com/v1/',
  	method: 'GET',
  	params: {
  		'url': url,
  		'apikey': apikey,
  		'response_type': 'plaintext',
  	},
  })
      .then(response => console.log(response.data))
      .catch(error => console.log(error));
  ```

  ```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}
  # gem install faraday
  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>

Let's say the HTML content of the ScrapingCourse product page includes a product title, a description, and a list of features. In HTML, it might look something like this:

```bash 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>
```

When you enable the `plaintext_response` feature, ZenRows Universal Scraper API will convert this HTML content into plain text like this:

```bash theme={null}
Product Title

This is a great product that does many things.

Feature 1
Feature 2
Feature 3
```

## PDF Response

In today's data-driven world, the ability to generate and save web scraping results in various formats can significantly enhance data utilization and sharing.

To use the PDF response feature, you must include the `js_render=true` parameter alongside with the `response_type` with the value `pdf` in your request. This instructs the API to generate a PDF file from the scraped content.

<Tip>Check our documentation about the [JS Rendering](/universal-scraper-api/features/js-rendering)</Tip>

<Warning>You can't use the PDF Response in conjunction with other outputs.</Warning>

The resulting PDF file will contain the same information as the web page you scraped.

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

  url = 'https://www.scrapingcourse.com/ecommerce/'
  apikey = 'YOUR_ZENROWS_API_KEY'
  params = {
      'url': url,
      'apikey': apikey,
      'js_render': 'true',
  	'response_type': 'pdf',
  }
  response = requests.get('https://api.zenrows.com/v1/', params=params)
  print(response.text)
  ```

  ```javascript Node.js theme={null}
  // npm install axios
  const axios = require('axios');

  const url = 'https://www.scrapingcourse.com/ecommerce/';
  const apikey = 'YOUR_ZENROWS_API_KEY';
  axios({
  	url: 'https://api.zenrows.com/v1/',
  	method: 'GET',
  	params: {
  		'url': url,
  		'apikey': apikey,
          'js_render': 'true',
  		'response_type': 'pdf',
  	},
  })
      .then(response => console.log(response.data))
      .catch(error => console.log(error));
  ```

  ```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&js_render=true&response_type=pdf";
          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&js_render=true&response_type=pdf');
  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&js_render=true&response_type=pdf", 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}
  # gem install faraday
  require 'faraday'

  url = URI.parse('https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.scrapingcourse.com%2Fecommerce%2F&js_render=true&response_type=pdf')
  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&js_render=true&response_type=pdf"
  ```
</CodeGroup>

After getting the response in `.pdf` you can save it using the following example in Python:

```python scraper.py theme={null}
# Save the response as a binary file
with open('output.pdf', 'wb') as file:
    file.write(response.content)

print("Response saved into output.pdf")
```

## Page Screenshot

Capture an above-the-fold screenshot of the target page by adding `screenshot=true` to the request. By default, the image will be in PNG format.

### Additional Options

<ul>
  <li>`screenshot_fullpage=true` takes a full-page screenshot.</li>
  <li>`screenshot_selector=<CSS Selector>` takes a screenshot of the element given in the CSS Selector.</li>
</ul>

Due to the nature of the params, `screenshot_selector` and `screenshot_fullpage` are mutually exclusive. Additionally, JavaScript rendering (`js_render=true`) is required.

These screenshot features can be combined with other options like `wait`, `wait_for`, or `js_instructions` to ensure that the page or elements are fully loaded before capturing the image. When using `json_response`, the result will include a JSON object with the screenshot data encoded in base64, allowing for easy integration into your workflows.

### Image Format and Quality

In addition to the basic screenshot functionality, ZenRows offers customization options to optimize the output. These features are particularly useful for reducing file size, especially when taking full-page screenshots where the image might exceed 10MB, causing errors.

<ul>
  <li>`screenshot_format`: Choose between `png` and `jpeg` formats, with PNG being the default. PNG is great for high-quality images and transparency, while JPEG offers efficient compression.</li>
  <li>`screenshot_quality`: Applicable when using JPEG, this parameter allows you to set the quality from `1` to `100`. Useful for balancing image clarity and file size, especially in scenarios where storage or bandwidth is limited.</li>
</ul>

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

  url = 'https://www.scrapingcourse.com/ecommerce/'
  apikey = 'YOUR_ZENROWS_API_KEY'
  params = {
      'url': url,
      'apikey': apikey,
  	'js_render': 'true',
      'screenshot_fullpage': 'true',
  }
  response = requests.get('https://api.zenrows.com/v1/', params=params)
  print(response.text)
  ```

  ```javascript Node.js theme={null}
  // npm install axios
  const axios = require('axios');
  const fs = require('fs');

  const url = 'https://www.scrapingcourse.com/ecommerce/';
  const apikey = 'YOUR_ZENROWS_API_KEY';
  axios({
      url: 'https://api.zenrows.com/v1/',
      method: 'GET',
      params: {
          'url': url,
          'apikey': apikey,
          'js_render': 'true',
          'screenshot': 'true',
          'screenshot_fullpage': 'true',
  	},
      responseType: 'stream',
  })
      .then(response => {
          const file = fs.createWriteStream('screenshot.png');
          response.data.pipe(file);
      })
      .catch(error => console.log(error));
  ```

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

  public class APIRequest {
      public static void main(final String... args) throws Exception {
          File file = new File("screenshot.png");
          String apiUrl = "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.scrapingcourse.com%2Fecommerce%2F&js_render=true&screenshot=true&screenshot_fullpage=true";
          Request.get(apiUrl).execute().saveContent(file);
      }
  }
  ```

  ```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&js_render=true&screenshot=true&screenshot_fullpage=true');
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  $response = curl_exec($ch);
  file_put_contents('screenshot.png', $response);
  curl_close($ch);
  ?>
  ```

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

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

  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&js_render=true&screenshot=true&screenshot_fullpage=true", nil)
  	if err != nil {
  		log.Fatalln(err)
  	}
  	resp, err := client.Do(req)
  	if err != nil {
  		log.Fatalln(err)
  	}
  	defer resp.Body.Close()

  	img, _ := os.Create("screenshot.png")
  	defer img.Close()

  	io.Copy(img, resp.Body)
  }
  ```

  ```ruby Ruby theme={null}
  # gem install faraday
  require 'faraday'

  url = URI.parse('https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.scrapingcourse.com%2Fecommerce%2F&js_render=true&screenshot=true&screenshot_fullpage=true')
  conn = Faraday.new()
  conn.options.timeout = 180
  res = conn.get(url, nil, nil)
  File.open('screenshot.png', 'wb') { |file| file.write(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&js_render=true&screenshot=true&screenshot_fullpage=true" > screenshot.png
  ```
</CodeGroup>

## Download Files and Pictures

ZenRows® lets you download images, PDFs, and other files directly from web pages. This feature is handy when extracting non-text content, like product images, manuals, or downloadable reports, as part of your web scraping workflow.

**Example:**

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

  url = 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf'
  apikey = 'YOUR_ZENROWS_API_KEY'
  params = {
      'url': url,
      'apikey': apikey,
  }
  response = requests.get('https://api.zenrows.com/v1/', params=params)

  # Save the PDF file as .pdf if the request is successful
  if response.status_code == 200:
      with open('output.pdf', 'wb') as f:
          f.write(response.content)
      print("File downloaded and saved successfully!")
  else:
      print(f"Failed to download the file. Status code: {response.text}")
  ```

  ```javascript Node.js theme={null}
  const fs = require('fs');
  const fetch = require('node-fetch');

  const apiKey = 'YOUR_ZENROWS_API_KEY';
  const targetUrl = 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf';

  const url = `https://api.zenrows.com/v1/?apikey=${apiKey}&url=${encodeURIComponent(targetUrl)}`;

  fetch(url)
    .then(res => {
      if (!res.ok) throw new Error(`Failed to download. Status: ${res.status}`);
      return res.buffer();
    })
    .then(data => {
      fs.writeFileSync('output.pdf', data);
      console.log('File downloaded and saved successfully!');
    })
    .catch(err => console.error('Error:', err.message));
  ```

  ```java Java theme={null}
  // Using HttpURLConnection
  import java.io.*;
  import java.net.*;

  public class DownloadFile {
      public static void main(String[] args) throws IOException {
          String targetUrl = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";
          String apiKey = "YOUR_ZENROWS_API_KEY";

          String requestUrl = "https://api.zenrows.com/v1/?apikey=" + apiKey + "&url=" + URLEncoder.encode(targetUrl, "UTF-8");

          URL url = new URL(requestUrl);
          HttpURLConnection connection = (HttpURLConnection) url.openConnection();

          if (connection.getResponseCode() == 200) {
              InputStream in = connection.getInputStream();
              FileOutputStream out = new FileOutputStream("output.pdf");

              byte[] buffer = new byte[4096];
              int n;
              while ((n = in.read(buffer)) != -1) {
                  out.write(buffer, 0, n);
              }

              out.close();
              in.close();
              System.out.println("File downloaded and saved successfully!");
          } else {
              System.out.println("Failed to download. Status code: " + connection.getResponseCode());
          }

          connection.disconnect();
      }
  }
  ```

  ```php PHP theme={null}
  <?php
  $targetUrl = 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf';
  $apiKey = 'YOUR_ZENROWS_API_KEY';

  $apiUrl = 'https://api.zenrows.com/v1/?apikey=' . $apiKey . '&url=' . urlencode($targetUrl);

  $response = file_get_contents($apiUrl);

  if ($response !== false) {
      file_put_contents('output.pdf', $response);
      echo "File downloaded and saved successfully!";
  } else {
      echo "Failed to download the file.";
  }
  ?>
  ```

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

  import (
  	"fmt"
  	"io"
  	"net/http"
  	"net/url"
  	"os"
  )

  func main() {
  	apiKey := "YOUR_ZENROWS_API_KEY"
  	targetUrl := "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"

  	requestUrl := fmt.Sprintf("https://api.zenrows.com/v1/?apikey=%s&url=%s", apiKey, url.QueryEscape(targetUrl))

  	resp, err := http.Get(requestUrl)
  	if err != nil {
  		fmt.Println("Error:", err)
  		return
  	}
  	defer resp.Body.Close()

  	if resp.StatusCode == 200 {
  		out, err := os.Create("output.pdf")
  		if err != nil {
  			fmt.Println("Error creating file:", err)
  			return
  		}
  		defer out.Close()

  		_, err = io.Copy(out, resp.Body)
  		if err != nil {
  			fmt.Println("Error saving file:", err)
  			return
  		}

  		fmt.Println("File downloaded and saved successfully!")
  	} else {
  		fmt.Println("Failed to download. Status code:", resp.Status)
  	}
  }
  ```

  ```ruby Ruby theme={null}
  require 'net/http'
  require 'uri'

  api_key = 'YOUR_ZENROWS_API_KEY'
  target_url = 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf'

  uri = URI("https://api.zenrows.com/v1/")
  uri.query = URI.encode_www_form({ 'apikey' => api_key, 'url' => target_url })

  response = Net::HTTP.get_response(uri)

  if response.is_a?(Net::HTTPSuccess)
    File.open('output.pdf', 'wb') { |file| file.write(response.body) }
    puts "File downloaded and saved successfully!"
  else
    puts "Failed to download. Status code: #{response.code}"
  end
  ```

  ```bash cURL theme={null}
  curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.w3.org%2FWAI%2FER%2Ftests%2Fxhtml%2Ftestfiles%2Fresources%2Fpdf%2Fdummy.pdf" -o output.pdf
  ```
</CodeGroup>

Supported file download scenarios:

<Steps>
  <Step title="Direct File Response">
    If the URL you request returns the file directly, such as an image or PDF link, ZenRows will fetch the file so you can save it in its original format. This is the most reliable method.
  </Step>

  <Step title="Triggered Downloads Using JS Instructions">
    If a file download is started by a user action, such as clicking a button or link, you can use ZenRows' JS Instructions to simulate these actions. If the download begins automatically, without prompting for a directory or further user input, ZenRows can capture and return the file.
  </Step>
</Steps>

<Note>Downloads are only possible when the file is delivered directly in the HTTP response. If the website asks the user to choose a download location or requires more interaction, ZenRows cannot capture the file. In these cases, we recommend using our [Scraping Browser](/scraping-browser/introduction), which gives you more control over the browser session and supports more complex interactions.</Note>

### File Size Limits

ZenRows enforces a maximum file size per request to ensure stable performance. If you try downloading a file larger than your plan allows, you will receive a `413 Content Too Large` error.

<Info>You can find more details on the plan limits on our [Pricing Documentation](https://docs.zenrows.com/first-steps/pricing)</Info>

## Frequently Asked Questions (FAQ)

<Accordion title="Can I use multiple response_type formats together?">
  No, certain `response_type` formats like Markdown, Plain Text, and PDF cannot be used together.
</Accordion>

<Accordion title="Why am I getting the original content instead of the specified response_type (Markdown, Plain Text, or PDF)?">
  For us to process the response as a `response_type` (Markdown, Plain Text, or PDF), we need to be able to parse the response as HTML. If we can't parse the response as HTML, we'll return the original response.

  When can this happen? When the response type is not `text/html` or when the response is not rendered.
</Accordion>

<Accordion title="How do I control the image quality and format for screenshots?">
  ZenRows supports customizing screenshots. You can choose between PNG (default) or JPEG formats using `screenshot_format`. For JPEGs, you can control the quality using `screenshot_quality`, with a value between `1` and `100`, to balance image clarity and file size.
</Accordion>

<Accordion title="How can I ensure that dynamic pages are fully loaded before scraping?">
  To ensure dynamic pages are fully loaded before scraping, you can use JavaScript rendering (`js_render=true`) and pair it with parameters like `wait` or `wait_for`. This ensures that ZenRows waits until the necessary elements are present on the page before scraping.
</Accordion>
