> For the complete documentation index, see [llms.txt](https://developers.oxylabs.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.oxylabs.io/products/pt-br/web-scraper-api/features/js-rendering-and-browser-control.md).

# Renderização de JS e controle do navegador

Aprenda como usar um parâmetro render para definir instruções do navegador na Web Scraper API, para que você possa fazer scraping de páginas dinâmicas complexas.

## Renderização de JavaScript

Se a página que você quer raspar usa JavaScript para carregar seus dados no DOM, adicione o `render` parâmetro à sua solicitação. A página então é totalmente renderizada antes de retornarmos o resultado, em um de dois formatos:

<table><thead><tr><th width="162.625">valor de render</th><th>Você obtém</th></tr></thead><tbody><tr><td><code>html</code></td><td>O HTML bruto da página totalmente renderizada</td></tr><tr><td><code>png</code></td><td>Uma captura de tela codificada em Base64 (PNG) da página renderizada</td></tr></tbody></table>

{% hint style="info" %}
Se você quiser raspar uma imagem e baixá-la, consulte [**esta seção**](/products/pt-br/web-scraper-api/features/result-processing-and-storage/output-types/download-images.md)**.**
{% endhint %}

### Exemplo de solicitação

{% tabs %}
{% tab title="cURL" %}

```shell
curl --user "USERNAME:PASSWORD" \
'https://realtime.oxylabs.io/v1/queries' \
-H "Content-Type: application/json" \
-d '{"source": "universal", "url": "https://www.example.com", "render": "html"}'
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
from pprint import pprint

# Structure payload.
payload = {
    'source': 'universal',
    'url': 'https://www.example.com',
    'render': 'html',
}

# Get response.
response = requests.request(
    'POST',
    'https://realtime.oxylabs.io/v1/queries',
    auth=('USERNAME', 'PASSWORD'),
    json=payload,
)

# Em vez de uma resposta com status do job e URL dos resultados, isso retornará a
# resposta JSON com o resultado.
pprint(response.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

$params = [
    'source' => 'universal',
    'url' => 'https://www.example.com',
    'render' => 'html',
];

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://realtime.oxylabs.io/v1/queries");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, "USERNAME" . ":" . "PASSWORD");

$headers = array();
$headers[] = "Content-Type: application/json";
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
echo $result;

if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
```

{% endtab %}

{% tab title="C#" %}

```csharp
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;

namespace OxyApi
{
    class Program
    {
        static async Task Main()
        {
            const string Username = "YOUR_USERNAME";
            const string Password = "YOUR_PASSWORD";

            var parameters = new Dictionary<string, string>()
            {
                { "source", "universal" },
                { "url", "https://www.example.com" },
                { "render" : "html" },
            };


            var client = new HttpClient();

            Uri baseUri = new Uri("https://realtime.oxylabs.io");
            client.BaseAddress = baseUri;

            var requestMessage = new HttpRequestMessage(HttpMethod.Post, "/v1/queries");
            requestMessage.Content = JsonContent.Create(parameters);

            var authenticationString = $"{Username}:{Password}";
            var base64EncodedAuthenticationString = Convert.ToBase64String(System.Text.ASCIIEncoding.UTF8.GetBytes(authenticationString));
            requestMessage.Headers.Add("Authorization", "Basic " + base64EncodedAuthenticationString);

            var response = await client.SendAsync(requestMessage);
            var contents = await response.Content.ReadAsStringAsync();

            Console.WriteLine(contents);
        }
    }
}
```

{% endtab %}

{% tab title="Golang" %}

```go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
)

func main() {
	const Username = "YOUR_USERNAME"
	const Password = "YOUR_PASSWORD"

	payload := map[string]string{
		"source": "universal",
		"url": "https://www.example.com",
        	"render": "html",
	}

	jsonValue, _ := json.Marshal(payload)

	client := &http.Client{}
	request, _ := http.NewRequest("POST",
		"https://realtime.oxylabs.io/v1/queries",
		bytes.NewBuffer(jsonValue),
	)

	request.SetBasicAuth(Username, Password)
	response, _ := client.Do(request)

	responseText, _ := ioutil.ReadAll(response.Body)
	fmt.Println(string(responseText))
}
```

{% endtab %}

{% tab title="Java" %}

```java
package org.example;

import okhttp3.*;
import org.json.JSONObject;

public class Main implements Runnable {
    private static final String AUTHORIZATION_HEADER = "Authorization";
    public static final String USERNAME = "YOUR_USERNAME";
    public static final String PASSWORD = "YOUR_PASSWORD";

    public void run() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("source", "universal");
        jsonObject.put("url", "https://www.example.com");
        jsonObject.put("render", "html");

        Authenticator authenticator = (route, response) -> {
            String credential = Credentials.basic(USERNAME, PASSWORD);

            return response
                    .request()
                    .newBuilder()
                    .header(AUTHORIZATION_HEADER, credential)
                    .build();
        };

        var client = new OkHttpClient.Builder()
                .authenticator(authenticator)
                .build();

        var mediaType = MediaType.parse("application/json; charset=utf-8");
        var body = RequestBody.create(jsonObject.toString(), mediaType);
        var request = new Request.Builder()
                .url("https://realtime.oxylabs.io/v1/queries")
                .post(body)
                .build();

        try (var response = client.newCall(request).execute()) {
            assert response.body() != null;
            System.out.println(response.body().string());
        } catch (Exception exception) {
            System.out.println("Error: " + exception.getMessage());
        }

        System.exit(0);
    }

    public static void main(String[] args) {
        new Thread(new Main()).start();
    }
}
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
import fetch from 'node-fetch';

const username = 'YOUR_USERNAME';
const password = 'YOUR_PASSWORD';
const body = {
  'source': 'universal',
  'url': 'https://www.example.com',
  'render': 'html'
};
const response = await fetch('https://realtime.oxylabs.io/v1/queries', {
  method: 'post',
  body: JSON.stringify(body),
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + Buffer.from(`${username}:${password}`).toString('base64'),
  }
});

console.log(await response.json());
```

{% endtab %}

{% tab title="JSON" %}

```json
{
    "source": "universal", 
    "url": "https://www.example.com", 
    "render": "html"
}
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
A renderização em JavaScript leva mais tempo para raspar a página. Defina um timeout no lado do cliente para 180 segundos se usar os métodos de integração Realtime ou Proxy Endpoint.
{% endhint %}

{% hint style="warning" %}
Para garantir o menor consumo de tráfego, nosso sistema não carrega ativos desnecessários durante a renderização da página.
{% endhint %}

## Forçando a renderização em páginas específicas

Para uma raspagem bem-sucedida, alguns tipos de página de domínios específicos exigem renderização devido ao conteúdo dinâmico. Para esses casos, nosso sistema **aplica a renderização automaticamente** mesmo que você não defina o `render` parâmetro, para que você sempre obtenha dados precisos e confiáveis dessas páginas, que de outra forma são difíceis.

{% hint style="warning" %}
Observe que jobs renderizados consomem mais tráfego em comparação com jobs não renderizados.
{% endhint %}

A lista completa dos alvos afetados é mantida no arquivo abaixo. Queremos que nossos usuários estejam plenamente cientes disso ao raspar as seguintes páginas:

{% file src="/files/379bd2517330d3f3329ac2abcb0543bb2cb19e78" %}

Se você quiser desativar a renderização, pode fazer isso adicionando o seguinte parâmetro às suas solicitações:

```
"render": ""
```

## Instruções do navegador

Quando uma página precisa de interação, como clicar em um botão, inserir um termo de busca ou rolar para carregar mais itens, você pode definir suas próprias `browser_instructions` que são executadas enquanto a página é renderizada.

{% hint style="success" %}
A maneira mais fácil de criar instruções do navegador é o construtor visual com IA no [Web Scraper API Playground](https://dashboard.oxylabs.io/?route=/api-playground). Leia sobre isso [aqui](/products/pt-br/web-scraper-api/web-scraper-api-playground/oxycopilot.md#browser-instruction-builder).
{% endhint %}

### Início rápido

Antes de tudo, as instruções do navegador exigem o `render` parâmetro, seja `html` ou `png`, e são fornecidas como uma lista no `browser_instructions` campo. Cada item da lista é executado em ordem.

Digamos que você queira pesquisar por `caixas de pizza` em um site — digite o termo no campo de busca, clique no botão de busca e espere 5 segundos para os resultados carregarem:

```json
{
    "source": "universal",
    "url": "https://www.etsy.com/",
    "render": "html",
    "browser_instructions": [
        {
            "type": "input",
            "value": "pizza boxes",
            "selector": {
                "type": "css",
                "value": "#global-enhancements-search-query"
            }
        },
        {
            "type": "click",
            "selector": {
                "type": "css",
                "value": "button[data-id='gnav-search-submit-button']"
            }
        },
        {
            "type": "wait",
            "wait_time_s": 5
        }
    ]
}
```

O resultado contém o HTML após a execução das instruções:

```json
{
  "results": [
    {
      "content": "<!DOCTYPE html><html lang=\"en-US\">  Search results for \"pizza boxes\"  </html>",
      "created_at": "2026-08-19 12:23:06",
      "updated_at": "2026-08-19 12:23:24",
      "page": 1,
      "url": "https://www.etsy.com/search?q=pizza+boxes&ref=search_bar&instant_download=false",
      "job_id": "7495817623108602881",
      "is_render_forced": false,
      "type": "raw",
      "status_code": 200
    }
  ]
}
```

O HTML raspado deve se parecer com isto:

<figure><img src="https://1795063165-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBQ7Zf9paoN3FTeGcyfY1%2Fuploads%2Fgit-blob-c2baf702d27346d7b1f44fb7493f478456ba8520%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Obtendo recursos do navegador <a href="#fetching-browser-resources" id="fetching-browser-resources"></a>

Fornecemos uma instrução de navegador independente para obter recursos do navegador.

A função é definida aqui:

Usando `fetch_resource` resultará no job retornando a primeira ocorrência de um recurso Fetch/XHR que corresponda ao formato fornecido, em vez do HTML que está sendo alvo.

Digamos que queremos direcionar um recurso GraphQL que é obtido quando se visita uma página de produto organicamente no navegador. Forneceremos as informações do job assim:

```json
{
    "source": "universal",
    "url": "https://petstore.swagger.io/",
    "render": "html",
    "browser_instructions": [
        {
            "type": "fetch_resource",
            "filter": "/v2/swagger.json"
        }
    ]
}
```

Essas instruções resultarão em um resultado assim:

```json
{
    "results": [
        {
            "content": "{\"swagger\":\"2.0\",\"info\":{\"description\":\"This is a sample server Petstore server. ...",
            "created_at": "2026-09-17 12:27:43",
            "updated_at": "2026-09-17 12:28:29",
            "page": 1,
            "url": "https://petstore.swagger.io/v2/swagger.json",
            "job_id": "7506328031753955329",
            "status_code": 200
        }
    ],
    "job": {...}
}
```

## Lista de instruções de navegador compatíveis <a href="#list-of-supported-browser-instructions" id="list-of-supported-browser-instructions"></a>

### Argumentos gerais

Todas as instruções definidas abaixo têm um conjunto consistente de argumentos. Os argumentos são os seguintes.

#### `tipo` <a href="#type" id="type"></a>

* **Tipo**: `Enum["click", "input", "scroll", "scroll_to_bottom", "wait", "wait_for_element", "fetch_resource"]`
* **Descrição:** Tipo de instrução do navegador.
* **Obrigatório**: `true`

#### `timeout_s` <a href="#timeout_s" id="timeout_s"></a>

* **Tipo**: `int`
* **Descrição:** Quanto tempo até a ação ser ignorada se não for concluída a tempo.
* **Restrições**: 0 < `timeout_s` <= 60
* **Valor padrão**: 5

#### `wait_time_s` <a href="#wait_time_s" id="wait_time_s"></a>

* **Tipo**: `int`
* **Descrição:** Quanto tempo esperar antes de executar a próxima ação.
* **Restrições**: 0 < `wait_time_s` <= 60
* **Valor padrão**: 0

#### `on_error` <a href="#on_error" id="on_error"></a>

* **Tipo**: `Enum["error", "skip"]`
* **Descrição:** Indicador do que fazer com as instruções caso esta instrução falhe:
  * `"error"`: Interrompe a execução das instruções do navegador.
  * `"skip"`: Continua com a próxima instrução.
* **Valor padrão**: `"error"`

#### Exemplo com argumentos gerais

```json
{
    "type": "wait_for_element",
    "selector": {
        "type": "text",
        "value": "Load More Items"
    },
    "timeout_s": 5,
    "wait_time_s": 2,
    "on_error": "skip"

}
```

### Instruções <a href="#click" id="click"></a>

#### `click` <a href="#click" id="click"></a>

* **Descrição**: Clica em um elemento e espera uma quantidade definida de segundos.
* **Argumentos:**
  * `type: str = "click"`
  * `selector: dict`
    * `type: Enum["xpath", "css", "text"]`
    * `value: str`

**Exemplo**:

```json
{
    "type": "click",
    "selector": {
        "type": "xpath",
        "value": "//button"
    }
}
```

#### `input` <a href="#input" id="input"></a>

* **Descrição**: Insere texto em um elemento selecionado.
* **Argumentos:**
  * `type: str = "input"`
  * `selector: dict`
    * `type: Enum["xpath", "css", "text"]`
    * `value: str`
  * `value: str`

**Exemplo:**

```json
{
    "type": "input",
    "selector": {
        "type": "xpath",
        "value": "//input"
    },
    "value": "pizza boxes"
}
```

#### `scroll` <a href="#scroll" id="scroll"></a>

* **Descrição**: Rola uma quantidade definida de pixels.
* **Argumentos:**
  * `type: str = "scroll"`
  * `x: int`
  * `y: int`

**Exemplo:**

```json
{
    "type": "scroll",
    "x": 0,
    "y": 100
}
```

#### `scroll_to_bottom` <a href="#scroll_to_bottom" id="scroll_to_bottom"></a>

* **Descrição**: Rola até o final por uma quantidade definida de segundos.
* **Argumentos:**
  * `type: str = "scroll_to_bottom"`

**Exemplo**:

```json
{
    "type": "scroll_to_bottom",
    "timeout_s": 10
}
```

#### `wait` <a href="#wait" id="wait"></a>

* **Descrição**: Aguarda uma quantidade definida de segundos.
* **Argumentos:**
  * `type: str = "wait"`

**Exemplo**:

```json
{
    "type": "wait",
    "wait_time_s": 2
}
```

#### `wait_for_element` <a href="#wait_for_element" id="wait_for_element"></a>

* **Descrição**: Aguarda o elemento carregar por uma quantidade definida de segundos.
* **Argumentos:**
  * `type: str = "wait_for_element"`
  * `selector: dict`
    * `type: Enum["xpath", "css", "text"]`
    * `value: str`

**Exemplo:**

```json
{
    "type": "wait_for_element",
    "selector": {
        "type": "text",
        "value": "Load More Items"
    },
    "timeout_s": 5
}
```

#### `fetch_resource` <a href="#fetch_resource" id="fetch_resource"></a>

{% hint style="warning" %}
A `fetch_resource` instrução deve ser a última instrução na lista de instruções do navegador; quaisquer instruções subsequentes não serão executadas.
{% endhint %}

* **Descrição**: Obtém a primeira ocorrência de um recurso Fetch/XHR que corresponda ao padrão definido.
* **Argumentos:**
  * `type: str = "fetch_resource"`
  * `filter: str(expressão RegEx)`
  * `on_error: Enum["error", "skip"]`

**Exemplo:**

```json
{
    "type": "fetch_resource",
    "filter": "/graphql/item/"
}
```

### Validação de instruções

Qualquer inconsistência em relação ao formato da instrução resultará em um `400` código de status e uma mensagem de erro correspondente.

Por exemplo, um payload como este:

```json
{
    "source": "universal",
    "url": "https://www.example.com/",
    "render": "html",
    "browser_instructions": [
        {
            "type": "unsupported-wait",
            "wait_time_s": 5
        }
    ]
}
```

Resultará em:

```json
{    
    "errors": {
        "message": "Tipo de ação não compatível `unsupported-wait`, escolha entre 'click,fetch_resource,input,scroll,scroll_to_bottom,wait,wait_for_element'"
    }
}
```

## Solução de problemas <a href="#status-codes" id="status-codes"></a>

### Códigos de status <a href="#status-codes" id="status-codes"></a>

Veja os códigos de resposta descritos [**aqui**](/products/pt-br/web-scraper-api/response-codes.md). Os códigos de status relacionados à validação de instruções estão documentados [**aqui**](#instruction-validation).

### Erros e avisos

Se houver um erro ou aviso resultante de suas ações de navegação, você o encontrará no resultado sob as chaves `browser_instructions_error` ou `browser_instructions_warnings`. Por exemplo, se você enviou as seguintes instruções do navegador e o esperado `xpath` não estiver localizado na página, o resultado incluirá um aviso.

`browser_instructions`:

```json
[
    {
        "type": "input", 
        "selector": {
            "type": "xpath",
            "value": "//input[@type='search']"
        },
        "value": "oxylabs"
    }
]
```

Resultados:

```json
{
  "results": [
    {
      "content": "<!doctype html><html>
        Conteúdo após executar as instruções      
      </html>",
      "created_at": "2023-10-11 11:35:23",
      "updated_at": "2023-10-11 11:36:08",
      "browser_instructions_warnings": [
        {
          "action_type": "click",
          "msg": "Não foi possível encontrar o tipo de seletor `xpath` com o valor `//input[@type=search]` na página."
        },
      ],
      "page": 1,
      "url": "https://example.com",
      "job_id": "7117835067442906113",
      "status_code": 200
    }
  ]
}

```

| Possíveis erros e avisos                                                                                 |
| -------------------------------------------------------------------------------------------------------- |
| Ocorreu um erro inesperado ao converter instruções do navegador em ações.                                |
| Ocorreu um erro inesperado ao executar `{action.type}` instruções do navegador.                          |
| Ação `{action.type}` excedeu o tempo limite.                                                             |
| Não foi possível encontrar o tipo de seletor `{selector.type}` com o valor `{selector.value}` na página. |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers.oxylabs.io/products/pt-br/web-scraper-api/features/js-rendering-and-browser-control.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
