> 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/es/web-scraper-api/features/js-rendering-and-browser-control.md).

# Renderizado de JS y control del navegador

## Renderizado de JavaScript

Si la página que desea extraer requiere JavaScript para cargar dinámicamente todos los datos necesarios en el DOM, puede incluir un `render` parámetro en sus solicitudes en lugar de configurar y usar instrucciones personalizadas del navegador manualmente. Las solicitudes con este parámetro se renderizarán por completo y los datos se almacenarán en un archivo HTML o en una captura de pantalla PNG, según el parámetro especificado.

### HTML

Establezca el `render` parámetro en `html` para obtener la salida sin procesar de la página renderizada.

### PNG (Captura de pantalla)

Establezca el `render` parámetro en `png` para obtener una captura de pantalla codificada en Base64 de la página renderizada.

{% hint style="info" %}
Si desea extraer una imagen y descargarla, consulte [**esta sección**](/products/es/web-scraper-api/features/result-processing-and-storage/output-types/download-images.md)**.**
{% endhint %}

### Ejemplo de solicitud

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

```shell
curl --user "user:pass" \\
'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=('user', 'pass1'),
    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, "user" . ":" . "pass1");

$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="HTTP" %}

```http
# The whole string you submit has to be URL-encoded.

https://realtime.oxylabs.io/v1/queries?source=universal&url=https%3A%2F%2Fwww.example.com%2F&render=html&access_token=12345abcde
```

{% endtab %}

{% tab title="JSON" %}

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

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
El renderizado de JavaScript tarda más en extraer la página. Establezca el tiempo de espera en el lado del cliente en 180 segundos si usa los métodos de integración Realtime o Proxy Endpoint.
{% endhint %}

{% hint style="warning" %}
Para garantizar el menor consumo de tráfico posible, nuestro sistema no carga recursos innecesarios durante el renderizado de la página.
{% endhint %}

## Forzar el renderizado en páginas específicas

Para extraer correctamente, algunos tipos de páginas de dominios específicos requieren renderizado debido a su contenido dinámico. Nuestro sistema aplica automáticamente el renderizado para estas páginas, incluso si no lo establece explícitamente el usuario.

{% hint style="warning" %}
Tenga en cuenta que los trabajos renderizados consumen más tráfico que los trabajos no renderizados.
{% endhint %}

Queremos que nuestros usuarios sean plenamente conscientes de esto al extraer las siguientes páginas:

{% file src="/files/86e1b6cb76dafac27758722af39d446efb3136c0" %}

Este enfoque proporciona la mejor experiencia de extracción posible, garantizando la precisión y la fiabilidad de los datos de estas páginas desafiantes.&#x20;

Si desea desactivar el renderizado, puede hacerlo añadiendo el siguiente parámetro a sus solicitudes:

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

## Instrucciones del navegador

Puede definir sus propias instrucciones del navegador que se ejecutan al renderizar JavaScript.

{% hint style="success" %}
La forma más sencilla de configurar instrucciones del navegador es usando el generador visual de instrucciones del navegador con IA en el [Web Scraper API Playground](https://dashboard.oxylabs.io/?route=/api-playground). Lea sobre ello [aquí](/products/es/web-scraper-api/web-scraper-api-playground/oxycopilot.md#browser-instruction-builder).
{% endhint %}

### Uso

Para usar las instrucciones del navegador, proporcione un conjunto de `browser_instructions` al crear un trabajo.

Supongamos que desea buscar el término `pizza boxes` en un sitio web.

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

Un ejemplo de parámetros del trabajo se vería así:

```json
{
    "source": "universal",
    "url": "https://www.ebay.com/",
    "render": "html",
    "browser_instructions": [
        {
            "type": "input",
            "value": "pizza boxes",
            "selector": {
                "type": "xpath",
                "value": "//input[@class='gh-tb ui-autocomplete-input']"
            }
        },
        {
            "type": "click",
            "selector": {
                "type": "xpath",
                "value": "//input[@type='submit']"
            }
        },
        {
            "type": "wait",
            "wait_time_s": 5
        }
    ]
}
```

**Paso 1.** Debe proporcionar el `"render": "html"` parámetro.

**Paso 2.** Las instrucciones del navegador deben describirse en el `"browser_instructions"` campo.

Las instrucciones de navegador de ejemplo anteriores especifican que el objetivo es introducir un término de búsqueda `pizza boxes` en un campo de búsqueda, hacer clic en el `buscar` botón y esperar 5 segundos a que el contenido se cargue.

El resultado extraído debería verse así:

```json
{
  "results": [
    {
      "content": "<!doctype html><html>
        Contenido después de ejecutar las instrucciones      
      </html>",
      "created_at": "2023-10-11 11:35:23",
      "updated_at": "2023-10-11 11:36:08",
      "page": 1,
      "url": "https://www.ebay.com/",
      "job_id": "7117835067442906113",
      "status_code": 200
    }
  ]
}
```

El HTML extraído debería verse así:

<figure><img src="/files/6572e2081885489deaa54ee69cc52995b054a9a4" alt=""><figcaption></figcaption></figure>

#### Obtención de recursos del navegador <a href="#fetching-browser-resources" id="fetching-browser-resources"></a>

Proporcionamos una instrucción de navegador independiente para obtener recursos del navegador.

La función se define aquí:

Uso de `fetch_resource` hará que el trabajo devuelva la primera ocurrencia de un recurso Fetch/XHR que coincida con el formato proporcionado, en lugar del HTML que se está buscando.

Supongamos que queremos apuntar a un recurso GraphQL que se obtiene al visitar de forma orgánica una página de producto en el navegador. Proporcionaremos la información del trabajo así:

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

Estas instrucciones darán como resultado algo así:

```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 instrucciones de navegador compatibles <a href="#list-of-supported-browser-instructions" id="list-of-supported-browser-instructions"></a>

### Argumentos generales

Todas las instrucciones definidas a continuación tienen un conjunto coherente de argumentos. Los argumentos son los siguientes.

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

* **Tipo**: `Enum["click", "input", "scroll", "scroll_to_bottom", "wait", "wait_for_element", "fetch_resource"]`
* **Descripción:** Tipo de instrucción del navegador.

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

* **Tipo**: `entero`
* **Descripción:** Tiempo hasta que la acción se omite si no se completa a tiempo.
* **Restricciones**: 0 < `timeout_s` <= 60
* **Valor predeterminado**: 5

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

* **Tipo**: `entero`
* **Descripción:** Tiempo de espera antes de ejecutar la siguiente acción.
* **Restricciones**: 0 < `wait_time_s` <= 60
* **Valor predeterminado**: 0

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

* **Tipo**: `Enum["error", "skip"]`
* **Descripción:** Indicador de qué hacer con las instrucciones en caso de que esta instrucción falle:
  * `"error"`: Detiene la ejecución de las instrucciones del navegador.
  * `"skip"`: Continúa con la siguiente instrucción.
* **Valor predeterminado**: `"error"`

#### Ejemplo con argumentos generales

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

}
```

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

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

* **Descripción**: Hace clic en un elemento y espera un número determinado de segundos.
* **Argumentos:**
  * `type: str = "click"`
  * `selector: dict`
    * `type: Enum["xpath", "css", "text"]`
    * `value: str`

**Ejemplo**:

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

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

* **Descripción**: Introduce texto en un elemento seleccionado.
* **Argumentos:**
  * `type: str = "input"`
  * `selector: dict`
    * `type: Enum["xpath", "css", "text"]`
    * `value: str`
  * `value: str`&#x20;

**Ejemplo:**

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

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

* **Descripción**: Desplaza un número determinado de píxeles.
* **Argumentos:**
  * `type: str = "scroll"`
  * `x: int`
  * `y: int`

**Ejemplo:**

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

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

* **Descripción**: Se desplaza hasta abajo durante un número determinado de segundos.
* **Argumentos:**
  * `type: str = "scroll_to_bottom"`

**Ejemplo**:

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

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

* **Descripción**: Espera un número determinado de segundos.
* **Argumentos:**
  * `type: str = "wait"`

**Ejemplo**:

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

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

* **Descripción**: Espera a que el elemento cargue durante un número determinado de segundos.
* **Argumentos:**
  * `type: str = "wait_for_element"`
  * `selector: dict`
    * `type: Enum["xpath", "css", "text"]`
    * `value: str`

**Ejemplo:**

```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" %}
La `fetch_resource` instrucción debe ser la última instrucción de la lista de instrucciones del navegador; cualquier instrucción posterior no se ejecutará.
{% endhint %}

* **Descripción**: Obtiene la primera ocurrencia de un recurso Fetch/XHR que coincida con el patrón establecido.
* **Argumentos:**
  * `type: str = "fetch_resource"`
  * `filter: str(RegEx expression)`
  * `on_error: Enum["error", "skip"]`

**Ejemplo:**

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

### Validación de instrucciones

Cualquier inconsistencia con respecto al formato de la instrucción dará lugar a un `400` código de estado y un mensaje de error correspondiente.

Por ejemplo, una carga útil como esta:

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

El resultado será:

```json
{    
    "errors": {
        "message": "Tipo de acción no admitido `unsupported-wait`, elige entre 'click,fetch_resource,input,scroll,scroll_to_bottom,wait,wait_for_element'"
    }
}
```

## Solución de problemas <a href="#status-codes" id="status-codes"></a>

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

Consulta nuestros códigos de respuesta descritos [**aquí**](/products/es/web-scraper-api/response-codes.md). Los códigos de estado relacionados con la validación de instrucciones se documentan [**aquí**](/products/es/web-scraper-api/features/js-rendering-and-browser-control.md#instruction-validation).

### Errores y advertencias

Si hay un error o advertencia como resultado de tus acciones de navegación, lo encontrarás en el resultado bajo las claves `browser_instructions_error` o `browser_instructions_warnings`. Por ejemplo, si has enviado las siguientes instrucciones del navegador y el esperado `xpath` no se encuentra en la página, el resultado incluirá una advertencia.

`browser_instructions`:

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

Resultados:

```json
{
  "results": [
    {
      "content": "<!doctype html><html>
        Contenido después de ejecutar las instrucciones      
      </html>",
      "created_at": "2023-10-11 11:35:23",
      "updated_at": "2023-10-11 11:36:08",
      "browser_instructions_warnings": [
        {
          "action_type": "click",
          "msg": "No se pudo encontrar el tipo de selector `xpath` con el valor `//input[@type=search]` en la página."
        },
      ],
      "page": 1,
      "url": "https://example.com",
      "job_id": "7117835067442906113",
      "status_code": 200
    }
  ]
}

```

| Posibles errores y advertencias                                                                          |
| -------------------------------------------------------------------------------------------------------- |
| Se produjo un error inesperado al convertir las instrucciones del navegador en acciones.                 |
| Se produjo un error inesperado al ejecutar `{action.type}` instrucciones del navegador.                  |
| Acción `{action.type}` agotó el tiempo.                                                                  |
| No se pudo encontrar el tipo de selector `{selector.type}` con el valor `{selector.value}` en la 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/es/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.
