> 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

## Renderização de JavaScript

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

<table><thead><tr><th width="162.625">valor de render</th><th>Você recebe</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 coletar 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 requisiçã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,
)

# Instead of response with job status and results url, this will return the
# JSON response with the result.
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 de JavaScript leva mais tempo para coletar a página. Defina o 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 coleta 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 seriam difíceis.

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

A lista completa dos alvos afetados é mantida no arquivo abaixo. Queremos que nossos usuários estejam totalmente cientes disso ao coletar as páginas a seguir:

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

Se quiser desativar a renderização, você pode fazer isso adicionando o seguinte parâmetro às suas requisiçõ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.

Suponha que você queira pesquisar `caixas de pizza` em um site — digite o termo no campo de pesquisa, clique no botão de busca e aguarde 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 depois que as instruções foram executadas:

```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 coletado deve se parecer com isto:

<figure><img src="/files/c17fd90bb0f8d582eba0e4a2c52332ea30a64055" alt=""><figcaption></figcaption></figure>

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

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

A função é definida aqui:

Usando `fetch_resource` fará com que a tarefa retorne a primeira ocorrência de um recurso Fetch/XHR que corresponda ao formato fornecido, em vez do HTML que está sendo alvo.

Suponha que queremos segmentar um recurso GraphQL que é buscado ao visitar uma página de produto organicamente no navegador. Forneceremos as informações da tarefa assim:

```json
{
    "source": "universal",
    "url": "https://www.example.com/product-page/123",
    "render": "html",
    "browser_instructions": [
        {
            "type": "fetch_resource",
            "filter": "/graphql/product-info/123"
        }
    ]
}
```

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

```json
{
  "results": [
    {
      "content": "{'product_id': 123, 'description': '', 'price': 123}",
      "created_at": "2023-10-11 11:35:23",
      "updated_at": "2023-10-11 11:36:08",
      "page": 1,
      "url": "https://example.com/v1/graphql/product-info/123/",
      "job_id": "7117835067442906114",
      "status_code": 200
    }
  ]
}
```

## Lista de instruções de navegador suportadas <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.

#### `type` <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:** 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:** Indica o 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 um número definido de segundos.
* **Args:**
  * `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 um texto em um elemento selecionado.
* **Args:**
  * `type: str = "input"`
  * `selector: dict`
    * `type: Enum["xpath", "css", "text"]`
    * `value: str`
  * `value: str`&#x20;

**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.
* **Args:**
  * `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 um número definido de segundos.
* **Args:**
  * `type: str = "scroll_to_bottom"`

**Exemplo**:

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

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

* **Descrição**: Aguarda um número definido de segundos.
* **Args:**
  * `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 um número definido de segundos.
* **Args:**
  * `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; qualquer instrução subsequente não será executada.
{% endhint %}

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

**Exemplo:**

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

### Validação da instrução

Qualquer inconsistência em relação ao formato das instruções resultará em um `400` código de status e em 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 suportado `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 nossos códigos de resposta descritos [**aqui**](/products/pt-br/web-scraper-api/response-codes.md). Os códigos de status em relação à validação das instruções estão documentados [**aqui**](/products/pt-br/web-scraper-api/features/js-rendering-and-browser-control.md#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 as instruções do navegador em ações.                             |
| Ocorreu um erro inesperado ao executar `{action.type}` as 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.
