> 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/integration-methods/push-pull.md).

# Push-Pull

Descubre el método de integración Push-Pull para Oxylabs Web Scraper API. Envía un trabajo y luego consulta más tarde el endpoint de resultados usando datos con formato JSON.

Push-Pull es nuestro método de integración recomendado para manejar de forma fiable grandes volúmenes de datos.

{% hint style="success" %}
Visita el repositorio de GitHub de Oxylabs para ver un ejemplo completo y funcional de [**integración Push-Pull en Python**](https://github.com/oxylabs/product-integrations/tree/master/scraper-apis/Python/push_pull).
{% endhint %}

Push-Pull es un método de integración asincrónico. Al enviar un trabajo, recibirás de inmediato una `JSON` respuesta que contiene todos los detalles del trabajo, incluidos los parámetros del trabajo, el ID y las URL para la descarga de resultados y la comprobación del estado. Una vez que tu trabajo se haya procesado, te informaremos mediante un `JSON` payload enviado a tu servidor, si proporcionaste un [**callback**](#callback) URL. Los resultados permanecerán disponibles para su recuperación durante **al menos 24 horas** después de la finalización.

Con Push-Pull, puedes cargar tus resultados directamente en tu [**almacenamiento en la nube**](/products/es/web-scraper-api/features/result-processing-and-storage/cloud-storage.md) (Google Cloud Storage, AWS S3, Alibaba Cloud OSS u otro almacenamiento compatible con S3).

{% hint style="info" %}
Si prefieres no configurar un servicio para notificaciones entrantes de callback, puedes simplemente recuperar tus resultados periódicamente (*sondeo*).
{% endhint %}

También puedes explorar cómo funciona Push-Pull usando [**Postman**](/integrations/es/web-scraper-api-integrations/postman.md).

## Trabajo único

### Punto final

Este punto final acepta solo una `consulta` o `URL` valor.

```
POST https://data.oxylabs.io/v1/queries
```

### Entrada

Proporciona los parámetros del trabajo en un payload JSON como se muestra en los ejemplos siguientes. Los ejemplos de Python y PHP incluyen comentarios para mayor claridad.

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

```shell
curl --user "USERNAME:PASSWORD" \\
'https://data.oxylabs.io/v1/queries' \\
-H "Content-Type: application/json" \\
 -d '{"source": "universal", "url": "https://www.example.com", "geo_location": "United States", "callback_url": "https://your.callback.url", "storage_type": "s3", "storage_url": "s3://your.storage.bucket.url"}'
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
from pprint import pprint


# Estructura el payload.
payload = {
    "source": "universal", # Fuente que eliges, por ejemplo, "universal"
    "url": "https://www.example.com", # Consulta la documentación de la fuente específica para ver si debes usar "url" o "query"
    "geo_location": "United States", # Algunas fuentes aceptan códigos postales o coordenadas
    #"render" : "html", # Descomenta si quieres renderizar JavaScript dentro de la página
    #"render" : "png", # Descomenta si quieres tomar una captura de pantalla de una página web extraída
    #"parse" : True, # Comprueba qué fuentes admiten datos parseados
    "callback_url": "https://your.callback.url", # Obligatorio si usas el escuchador de callback
    "storage_type": "s3", 
    "storage_url": "s3://your.storage.bucket.url"
}

# Obtén la respuesta.
response = requests.request(
    'POST',
    'https://data.oxylabs.io/v1/queries',
    auth=('YOUR_USERNAME', 'YOUR_PASSWORD'), #Tus credenciales van aquí
    json=payload,
)

# Imprime la respuesta formateada en stdout.
pprint(response.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

$params = array(
    'source' => 'universal', // Fuente que eliges, por ejemplo, "universal"
    'url' => 'https://www.example.com', // Consulta la documentación de la fuente específica para ver si debes usar "url" o "query"
    'geo_location' => 'United States', // Algunas fuentes aceptan códigos postales o coordenadas
    //'render' => 'html', // Descomenta si quieres renderizar JavaScript dentro de la página
    //'render' => 'png', // Descomenta si quieres tomar una captura de pantalla de una página web extraída
    //'parse' => TRUE, // Comprueba qué fuentes admiten datos parseados
    'callback_url' => 'https://your.callback.url', // Obligatorio si usas el escuchador de callback
    'storage_type' => 's3',
    'storage_url' => 's3://your.storage.bucket.url'
);

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://data.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, "YOUR_USERNAME" . ":" . "YOUR_PASSWORD"); //Tus credenciales van aquí

$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://example.com" },
                { "geo_location", "United States" },
                { "callback_url", "https://your.callback.url" },
            };


            var client = new HttpClient();

            Uri baseUri = new Uri("https://data.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://example.com",
		"geo_location": "United States",
		"callback_url": "https://your.callback.url",
	}

	jsonValue, _ := json.Marshal(payload)

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

	request.Header.Add("Content-type", "application/json")
	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://example.com");
        jsonObject.put("geo_location", "United States");
        jsonObject.put("callback_url", "https://your.callback.url");

        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://data.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',
  geo_location: 'United States',
  callback_url: 'https://your.callback.url',
};
const response = await fetch('https://data.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 %}
{% endtabs %}

### Salida

La API responderá con un JSON que contiene la información del trabajo, similar a esto:

```json
{
  "callback_url": "https://your.callback.url",
  "client_id": 5,
  "context": [
    {...}
  ],
  "created_at": "2026-09-03 00:00:01",
  "domain": "com",
  "geo_location": "United States",
  "id": "12345678900987654321",
  "limit": 10,
  "locale": null,
  "pages": 1,
  "parse": false,
  "parser_type": null,
  "parser_preset": null,
  "parsing_instructions": null,
  "browser_instructions": null,
  "render": null,
  "xhr": false,
  "markdown": false,
  "url": "https://www.example.com",
  "query": "",
  "source": "universal",
  "start_page": 1,
  "status": "pending",
  "storage_type": "s3",
  "storage_url": "YOUR_BUCKET_NAME/12345678900987654321.json",
  "aggregate_name": null,
  "subdomain": "www",
  "content_encoding": "utf-8",
  "updated_at": "2026-09-03 00:00:01",
  "user_agent_type": "desktop",
  "session_info": null,
  "statuses": [],
  "client_notes": null,
  "_links": [
    {
      "rel": "self",
      "href": "http://data.oxylabs.io/v1/queries/12345678900987654321",
      "method": "GET"
    },
    {
      "rel": "results",
      "href": "http://data.oxylabs.io/v1/queries/12345678900987654321/results",
      "method": "GET"
    },
    {
      "rel": "results-content",
      "href_list": [
        "http://data.oxylabs.io/v1/queries/12345678900987654321/results/1/content"
      ],
      "method": "GET"
    },
    {
      "rel": "results-html",
      "href": "http://data.oxylabs.io/v1/queries/12345678900987654321/results?type=raw",
      "method": "GET"
    },
    {
      "rel": "results-content-html",
      "href_list": [
        "http://data.oxylabs.io/v1/queries/12345678900987654321/results/1/content?type=raw"
      ],
      "method": "GET"
    }
  ]
}
```

### Diccionario de datos

La tabla siguiente describe los campos devueltos en la respuesta del trabajo. Para los parámetros de entrada que puedes enviar, consulta la página de documentación de la fuente que estés usando.

<table><thead><tr><th>Clave</th><th width="500.90234375">Descripción</th><th width="114.53125">Tipo</th></tr></thead><tbody><tr><td><code>created_at</code></td><td>La fecha y hora en que se creó el trabajo.</td><td>Cadena</td></tr><tr><td><code>client_id</code></td><td>El ID numérico asociado al nombre de usuario del cliente que realiza la solicitud.</td><td>Cadena</td></tr><tr><td><code>client_notes</code></td><td>Notas enviadas por el cliente al enviar un trabajo.</td><td>Cadena</td></tr><tr><td><code>content_encoding</code></td><td>La codificación del contenido devuelto. Establécela en tu payload cuando <a href="/products/es/web-scraper-api/features/result-processing-and-storage/output-types/download-images.md"><strong>descargando imágenes</strong></a>; se devuelve en la respuesta del trabajo.</td><td>Cadena</td></tr><tr><td><code>id</code></td><td>El ID único del trabajo.</td><td>Cadena</td></tr><tr><td><code>statuses</code></td><td>Los códigos de estado del trabajo de scraping o parseo. Puedes ver los códigos de estado descritos <a href="/products/es/web-scraper-api/response-codes.md"><strong>aquí</strong></a>.</td><td>Entero</td></tr><tr><td><code>status</code></td><td>El estado del trabajo. <code>pending</code> significa que el trabajo todavía se está procesando. <code>done</code> significa que hemos completado el trabajo. <code>faulted</code> significa que encontramos errores al intentar completar el trabajo y desistimos.</td><td>Cadena</td></tr><tr><td><code>subdomain</code></td><td>El subdominio del sitio web.</td><td>Cadena</td></tr><tr><td><code>updated_at</code></td><td>La fecha y hora de la última actualización del trabajo. Para los trabajos que están terminados (<code>status</code> is <code>done</code> o <code>faulted</code>), esta fecha y hora indica cuándo se terminó el trabajo.</td><td>Cadena</td></tr><tr><td><code>_links</code></td><td>La lista de enlaces, relacionados con la entrada proporcionada.</td><td>Arreglo JSON</td></tr><tr><td><code>_links</code>:<code>rel</code></td><td>El tipo de enlace. <code>self</code> La URL contiene los metadatos del trabajo, mientras que <code>results</code> la URL contiene los resultados del trabajo.</td><td>Cadena</td></tr><tr><td><code>_links</code>:<code>href</code></td><td>La URL del recurso.</td><td>Cadena</td></tr><tr><td><code>_links</code>:<code>href_list</code></td><td>La lista de URL del recurso, una por página. Devuelta <strong>en lugar de</strong> <code>href</code> en entradas cuyo <code>rel</code> empieza con <code>results-content</code>. Consulta <a href="#retrieve-job-content"><strong>Recuperar contenido del trabajo</strong></a>.</td><td>Arreglo JSON</td></tr><tr><td><code>_links</code>:<code>method</code></td><td>El método HTTP que debe usarse para interactuar con una URL determinada.</td><td>Cadena</td></tr></tbody></table>

## Callback

El callback es una solicitud `POST` que enviamos a tu máquina, informando de que la tarea de extracción de datos se ha completado y proporcionando una URL para descargar el contenido extraído. Esto significa que no necesitas [**comprobar el estado del trabajo**](#check-job-status) manualmente. Una vez que los datos estén aquí, te avisaremos, y todo lo que necesitas hacer ahora es [**recuperarlos**](#retrieve-job-content).

### Entrada

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

```python
# Este es un servidor web Sanic sencillo con una ruta que escucha callbacks en localhost:8080.
# Imprimirá los resultados del trabajo en stdout.
import requests
from pprint import pprint
from sanic import Sanic, response


AUTH_TUPLE = ('user', 'pass1')

app = Sanic()


# Define el endpoint /job_listener que acepta solicitudes POST.
@app.route('/job_listener', methods=['POST'])
async def job_listener(request):
    try:
        res = request.json
        links = res.get('_links', [])
        for link in links:
            if link['rel'] == 'results':
                # Sanic is async, but requests are synchronous, to fully take
                # advantage of Sanic, use aiohttp.
                res_response = requests.request(
                    method='GET',
                    url=link['href'],
                    auth=AUTH_TUPLE,
                )
                pprint(res_response.json())
                break
    except Exception as e:
        print("Listener exception: {}".format(e))
    return response.json(status=200, body={'status': 'ok'})


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
$stdout = fopen('php://stdout', 'w');

if (isset($_POST)) {
    $result = array_merge($_POST, (array) json_decode(file_get_contents('php://input')));

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, "https://data.oxylabs.io/v1/queries/".$result['id'].'/results');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
    curl_setopt($ch, CURLOPT_USERPWD, "user" . ":" . "pass1");

    $result = curl_exec($ch);
    fwrite($stdout, $result);

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

{% endtab %}

{% tab title="C#" %}

```csharp
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Net.Http;

namespace OxyApiWeb
{
    public class Callback
    {
        public Link[] _links { get; set; }
    }

    public class Link
    {
        public string rel { get; set; }
        public string href { get; set; }
    }

    public class Startup
    {
        private const string USERNAME = "YOUR_USERNAME";
        private const string PASSWORD = "YOUR_PASSWORD";

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;

            client = new HttpClient();
        }

        public IConfiguration Configuration { get; }

        private HttpClient client;

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapPost("/job_listener", async context =>
                {
                    var callback = await System.Text.Json.JsonSerializer.DeserializeAsync<Callback>(context.Request.Body);

                    foreach (var link in callback._links)
                    {
                        if (link.rel != "results")
                        {
                            continue;
                        }

                        var requestMessage = new HttpRequestMessage(HttpMethod.Get, new Uri(link.href));

                        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);

                    }

                    var okMessage = new Dictionary<string, string>()
                    {
                        { "message", "ok" }
                    };

                    await System.Text.Json.JsonSerializer.SerializeAsync(context.Response.Body, okMessage);
                });
            });
        }
    }
}

```

{% endtab %}

{% tab title="Golang" %}

```go
package main

import (
	"fmt"
	"github.com/labstack/echo/v4"
	"io/ioutil"
	"net/http"
)

const Username = "YOUR_USERNAME"
const Password = "YOUR_PASSWORD"

type Callback struct {
	Links []Link `json:"_links"`
}

type Link struct {
	Href string `json:"href"`
	Method string `json:"method"`
	Rel string `json:"rel"`
}

func main() {
	echoServer := echo.New()
	client := &http.Client{}

	echoServer.POST("/job_listener", func(context echo.Context) error {
		callback := new(Callback)
		if err := context.Bind(callback); err != nil {
			return err
		}

		for _, link := range callback.Links {
			if link.Rel != "results" {
				continue
			}

			request, _ := http.NewRequest("GET",
				link.Href,
				nil,
			)

			request.Header.Add("Content-type", "application/json")
			request.SetBasicAuth(Username, Password)
			response, _ := client.Do(request)

			responseText, _ := ioutil.ReadAll(response.Body)
			fmt.Println(string(responseText))
		}
		return context.JSON(http.StatusOK, map[string]string { "status": "ok" })
	})

	echoServer.Logger.Fatal(echoServer.Start(":8080"))
}
```

{% endtab %}

{% tab title="Java" %}

```java
package org.example;

import okhttp3.*;
import com.sun.net.httpserver.HttpServer;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;

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() {
        HttpServer server = null;
        try {
            server = HttpServer.create(new InetSocketAddress("0.0.0.0", 8080), 0);
        } catch (IOException exception) {
            exception.printStackTrace();
            System.exit(1);
        }

        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();

        server.createContext("/job_listener", exchange -> {
            var requestBody = IOUtils.toString(exchange.getRequestBody(), StandardCharsets.UTF_8);
            JSONObject requestJson = new JSONObject(requestBody);
            JSONArray links = requestJson.getJSONArray("_links");
            for (var link : links.toList()) {
                var linkMap = (Map<?, ?>)link;
                if (!Objects.equals(linkMap.get("rel"), "results")) {
                    continue;
                }

                var request = new Request.Builder()
                        .url((String) linkMap.get("href"))
                        .get()
                        .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());
                }
            }

            var responseJson = new JSONObject();
            responseJson.put("status", "ok");
            exchange.sendResponseHeaders(200, responseJson.toString().length());

            OutputStream responseBody = exchange.getResponseBody();
            responseBody.write(responseJson.toString().getBytes());
            responseBody.flush();
            responseBody.close();

            exchange.close();
        });
        server.setExecutor(null);
        server.start();
    }

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

{% endtab %}

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

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

const username = 'YOUR_USERNAME';
const password = 'YOUR_PASSWORD';

const app = express();
app.use(express.json());

app.post('/job_listener', async(request, response) => {
  for (const index in request.body._links) {
    const link = request.body._links[index];
    if (link.rel !== 'results') {
      continue;
    }

    const jobResultResponse = await fetch(link.href, {
      method: 'get',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + Buffer.from(`${username}:${password}`).toString('base64'),
      }
    });

    console.log(await jobResultResponse.json());
  }

  response.send({status: 'ok'});
});

app.listen(8080);
```

{% endtab %}
{% endtabs %}

### Salida

```json
{
  "callback_url": "https://your.callback.url",
  "client_id": 5,
  "context": [
    {...}
  ],
  "created_at": "2026-09-03 00:00:01",
  "domain": "com",
  "geo_location": "United States",
  "id": "12345678900987654321",
  "limit": 10,
  "locale": null,
  "pages": 1,
  "parse": false,
  "parser_type": null,
  "parser_preset": null,
  "parsing_instructions": null,
  "browser_instructions": null,
  "render": null,
  "xhr": false,
  "markdown": false,
  "url": "https://www.example.com",
  "query": "",
  "source": "universal",
  "start_page": 1,
  "status": "done",
  "storage_type": null,
  "storage_url": null,
  "aggregate_name": null,
  "subdomain": "www",
  "content_encoding": "utf-8",
  "updated_at": "2026-09-03 00:00:15",
  "user_agent_type": "desktop",
  "session_info": null,
  "statuses": [],
  "client_notes": null,
  "_links": [
    {
      "rel": "self",
      "href": "http://data.oxylabs.io/v1/queries/12345678900987654321",
      "method": "GET"
    },
    {
      "rel": "results",
      "href": "http://data.oxylabs.io/v1/queries/12345678900987654321/results",
      "method": "GET"
    },
    {
      "rel": "results-content",
      "href_list": [
        "http://data.oxylabs.io/v1/queries/12345678900987654321/results/1/content"
      ],
      "method": "GET"
    },
    {
      "rel": "results-html",
      "href": "http://data.oxylabs.io/v1/queries/12345678900987654321/results?type=raw",
      "method": "GET"
    },
    {
      "rel": "results-content-html",
      "href_list": [
        "http://data.oxylabs.io/v1/queries/12345678900987654321/results/1/content?type=raw"
      ],
      "method": "GET"
    }
  ]
}
```

## Comprobar el estado del trabajo

Si proporcionó una URL de callback válida al enviar su trabajo, le notificaremos al completarse enviando una `JSON` carga útil a la URL de callback especificada. Esta carga útil indicará que el trabajo se ha completado y su estado se ha establecido en `done`.

Sin embargo, si envió un trabajo sin usar [**el servicio de Callback**](#callback), puede comprobar el estado del trabajo manualmente. Obtenga la URL del `href` campo en la `rel:self` sección del mensaje de respuesta recibido después de enviar el trabajo. La URL para comprobar el estado del trabajo será similar a la siguiente: `http://data.oxylabs.io/v1/queries/12345678900987654321`. Consultar esta URL devolverá la información del trabajo, incluido su estado actual `status`.

### Punto final

```
GET https://data.oxylabs.io/v1/queries/{id}
```

### Entrada

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

```bash
curl --user "USERNAME:PASSWORD" \\
'https://data.oxylabs.io/v1/queries/12345678900987654321'
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
from pprint import pprint

# Get response from stats endpoint.
response = requests.request(
    method='GET',
    url='https://data.oxylabs.io/v1/queries/12345678900987654321',
    auth=('user', 'pass1'),
)

# Print prettified JSON response to stdout.
pprint(response.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://data.oxylabs.io/v1/queries/12345678900987654321");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_USERPWD, "user" . ":" . "pass1");

$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 JobId = "12345678900987654321";
            const string Username = "YOUR_USERNAME";
            const string Password = "YOUR_PASSWORD";

            var client = new HttpClient();

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

            var requestMessage = new HttpRequestMessage(HttpMethod.Get, $"/v1/queries/{JobId}");

            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 (
	"fmt"
	"io/ioutil"
	"net/http"
)

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

	client := &http.Client{}
	request, _ := http.NewRequest("GET",
		fmt.Sprintf("https://data.oxylabs.io/v1/queries/%s", JobId),
		nil,
	)

	request.Header.Add("Content-type", "application/json")
	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.*;

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

    public void run() {
        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 request = new Request.Builder()
                .url(String.format("https://data.oxylabs.io/v1/queries/%s", JOB_ID))
                .get()
                .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 jobId = '12345678900987654321';
const username = 'YOUR_USERNAME';
const password = 'YOUR_PASSWORD';
const response = await fetch(`https://data.oxylabs.io/v1/queries/${jobId}`, {
  method: 'get',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + Buffer.from(`${username}:${password}`).toString('base64'),
  }
});

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

{% endtab %}
{% endtabs %}

### Salida

Al completarse el trabajo, la API responderá con la información de la consulta en formato JSON. El estado del trabajo cambiará a `done`, lo que indica que el trabajo ha finalizado. Puede obtener el contenido consultando uno de los enlaces proporcionados. Además, la respuesta incluirá la marca de tiempo de la última actualización del trabajo, lo que le permitirá seguir su tiempo de procesamiento.

```json
{
    "callback_url": null,
    "client_id": 5,
    "context": [
        {...}
    ],
    "created_at": "2026-09-03 00:00:01",
    "domain": "com",
    "geo_location": "United States",
    "id": "12345678900987654321",
    "limit": 10,
    "locale": null,
    "pages": 1,
    "parse": false,
    "parser_type": null,
    "parser_preset": null,
    "parsing_instructions": null,
    "browser_instructions": null,
    "render": null,
    "xhr": false,
    "markdown": false,
    "url": "https://www.example.com",
    "query": "",
    "source": "universal",
    "start_page": 1,
    "status": "done",
    "storage_type": null,
    "storage_url": null,
    "aggregate_name": null,
    "subdomain": "www",
    "content_encoding": "utf-8",
    "updated_at": "2026-09-03 00:00:15",
    "user_agent_type": "desktop",
    "session_info": null,
    "statuses": [],
    "client_notes": null,
    "_links": [
        {
            "rel": "self",
            "href": "http://data.oxylabs.io/v1/queries/12345678900987654321",
            "method": "GET"
        },
        {
            "rel": "results",
            "href": "http://data.oxylabs.io/v1/queries/12345678900987654321/results",
            "method": "GET"
        },
        {
            "rel": "results-content",
            "href_list": [
                "http://data.oxylabs.io/v1/queries/12345678900987654321/results/1/content"
            ],
            "method": "GET"
        },
        {
            "rel": "results-html",
            "href": "http://data.oxylabs.io/v1/queries/12345678900987654321/results?type=raw",
            "method": "GET"
        },
        {
            "rel": "results-content-html",
            "href_list": [
                "http://data.oxylabs.io/v1/queries/12345678900987654321/results/1/content?type=raw"
            ],
            "method": "GET"
        }
    ]
}
```

## Valores de estado

<table><thead><tr><th width="150">Parámetro</th><th>Descripción</th></tr></thead><tbody><tr><td><code>pending</code></td><td>El trabajo aún se está procesando y no se ha completado.</td></tr><tr><td><code>done</code></td><td>El trabajo se ha completado. Puede obtener el resultado consultando la URL proporcionada en el <code>href</code> campo bajo la <code>rel:results</code> sección, por ejemplo: <code>http://data.oxylabs.io/v1/queries/12345678900987654321/results</code>.</td></tr><tr><td><code>faulted</code></td><td>Hubo un problema con el trabajo y no pudimos completarlo. No se le cobrará por ningún <code>faulted</code> trabajo.</td></tr></tbody></table>

## Recuperar contenido del trabajo

Una vez que el trabajo esté listo para recuperarse, puede usar la URL proporcionada en la respuesta bajo la `rel:results` sección. La URL tendrá este aspecto: `http://data.oxylabs.io/v1/queries/12345678900987654321/results`.

{% hint style="info" %}
Las `_links` URL se devuelven con un `http://` esquema. Sustitúyalo por `https://` antes de llamarlas, para que sus credenciales no se envíen sin cifrar.
{% endhint %}

### Endpoints

Puede obtener distintos tipos de resultados usando los siguientes endpoints:

```
GET https://data.oxylabs.io/v1/queries/{job_id}/results
```

```
GET https://data.oxylabs.io/v1/queries/{job_id}/results?type=raw
```

```
GET https://data.oxylabs.io/v1/queries/{job_id}/results?type=parsed
```

```
GET https://data.oxylabs.io/v1/queries/{job_id}/results?type=png
```

```
GET https://data.oxylabs.io/v1/queries/{job_id}/results?type=xhr
```

```
GET https://data.oxylabs.io/v1/queries/{job_id}/results?type=markdown
```

También puede obtener [múltiples tipos de resultado](/products/es/web-scraper-api/features/result-processing-and-storage/output-types/multi-format-output.md) en una sola respuesta, por ejemplo:

```
GET https://data.oxylabs.io/v1/queries/{job_id}/results?type=parsed,raw
```

Para obtener una sola página como contenido sin procesar, en lugar de dentro de un objeto JSON, use el endpoint content, donde `{n}` es el número de página, comenzando en `1`. Los mismos `valores de tipo` se aplican.

```
GET https://data.oxylabs.io/v1/queries/{job_id}/results/{n}/content
```

### Entrada

A continuación se muestran ejemplos de código que demuestran cómo usar el `/results` endpoint:

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

```shell
curl --user "USERNAME:PASSWORD" \\
'https://data.oxylabs.io/v1/queries/12345678900987654321/results'
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
from pprint import pprint

# Get response from stats endpoint.
response = requests.request(
    method='GET',
    url='https://data.oxylabs.io/v1/queries/12345678900987654321/results',
    auth=('user', 'pass1'),
)

# Print prettified JSON response to stdout.
pprint(response.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://data.oxylabs.io/v1/queries/12345678900987654321/results");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_USERPWD, "user" . ":" . "pass1");

$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.Net.Http;
using System.Threading.Tasks;

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

            var client = new HttpClient();

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

            var requestMessage = new HttpRequestMessage(HttpMethod.Get, $"/v1/queries/{JobId}/results");

            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 (
	"fmt"
	"io/ioutil"
	"net/http"
)

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

	client := &http.Client{}
	request, _ := http.NewRequest("GET",
		fmt.Sprintf("https://data.oxylabs.io/v1/queries/%s/results", JobId),
		nil,
	)

	request.Header.Add("Content-type", "application/json")
	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.*;

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

    public void run() {
        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 request = new Request.Builder()
                .url(String.format("https://data.oxylabs.io/v1/queries/%s/results", JOB_ID))
                .get()
                .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 jobId = '12345678900987654321';
const username = 'YOUR_USERNAME';
const password = 'YOUR_PASSWORD';
const response = await fetch(`https://data.oxylabs.io/v1/queries/${jobId}/results`, {
  method: 'get',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + Buffer.from(`${username}:${password}`).toString('base64'),
  }
});

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

{% endtab %}
{% endtabs %}

### Salida

Esta tabla explica el tipo de resultado predeterminado según los parámetros incluidos en la carga útil de la solicitud de la API.

| Parámetro Render | Parámetro Parse | Parámetro XHR | Salida predeterminada |
| ---------------- | --------------- | ------------- | --------------------- |
| -                | -               | -             | html                  |
| `html`           | -               | -             | html                  |
| `html`           | -               | `true`        | xhr                   |
| `html`           | `true`          | `true`        | parsed                |
| `png`            | -               | -             | png                   |
| -                | `true`          | -             | parsed                |
| `html`           | `true`          | -             | parsed                |
| `png`            | `true`          | -             | png                   |

De forma predeterminada, el `/results` endpoint devuelve solo la salida predeterminada para su carga útil. Para recibir tipos de resultado adicionales, añada el `valores de tipo` parámetro de consulta mostrado debajo de [**Endpoints**](/products/es/web-scraper-api/integration-methods/push-pull.md#endpoints) anterior. Cada tipo solicitado se devuelve como una entrada separada en el `results` arreglo. Esta es la [**múltiples tipos de resultado**](/products/es/web-scraper-api/features/result-processing-and-storage/output-types/multi-format-output.md) característica, y funciona igual en Push-Pull y [**Realtime**](/products/es/web-scraper-api/integration-methods/realtime.md).

A continuación se muestra una respuesta de ejemplo del `/results` endpoint. Junto con `results`, devuelve un `objeto de trabajo` que contiene los mismos detalles del trabajo descritos en la [**Diccionario de datos**](#data-dictionary), abreviado aquí. Algunas fuentes también devuelven `_request`, `_response` y `session_info` en cada resultado.

```json
{
  "results": [
    {
      "content": "<!doctype html><html>CONTENT</html>",
      "created_at": "2026-09-03 00:00:01",
      "updated_at": "2026-09-03 00:00:15",
      "page": 1,
      "url": "https://www.example.com",
      "job_id": "12345678900987654321",
      "is_render_forced": false,
      "status_code": 200,
      "type": "raw",
      "_request": {
        "cookies": [],
        "headers": {...}
      },
      "_response": {
        "cookies": [],
        "headers": {...}
      },
      "session_info": {
        "expires_at": null,
        "id": null,
        "remaining": null
      }
    }
  ],
  "job": {...}
}
```

Los resultados pueden recuperarse automáticamente sin comprobar periódicamente el estado del trabajo mediante la configuración del [**Callback**](#callback) servicio de Callback. Para ello, especifique la URL de un servidor que pueda aceptar solicitudes HTTP(S) entrantes al enviar un trabajo. Cuando nuestro sistema complete el trabajo, enviará `POST` una carga útil JSON a la URL proporcionada, y el servicio de Callback descargará los resultados como se describe en el [**ejemplo de implementación de Callback**](#callback).

## Consulta por lotes

Scraper APIs admite enviar hasta 5.000 `consulta` o `url` valores del parámetro url en una sola solicitud por lotes.

### Punto final

```
POST https://data.oxylabs.io/v1/queries/batch
```

El sistema procesará cada `consulta` o `url` palabra clave enviada como un trabajo independiente. Si proporciona una URL de callback, recibirá una llamada independiente por cada palabra clave. De lo contrario, nuestra respuesta inicial contendrá ID de trabajo `id`s para todas las palabras clave. Por ejemplo, si envió 50 palabras clave, devolveremos 50 IDs de trabajo únicos `id`.

{% hint style="info" %}
**IMPORTANTE:** Con `/batch` endpoint, solo puede enviar listas de `consulta`o `url`valores del parámetro (según el `origen` que use). Todos los demás parámetros deben tener valores singulares.
{% endhint %}

### Entrada

Debe enviar los parámetros de consulta como una carga útil JSON. Así se envía un trabajo por lotes:

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

```shell
curl --user "USERNAME:PASSWORD" \\
'https://data.oxylabs.io/v1/queries/batch' \
-H 'Content-Type: application/json' \
-d '@keywords.json'
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
import json
from pprint import pprint


# Get payload from file.
with open('keywords.json', 'r') as f:
    payload = json.loads(f.read())

response = requests.request(
    'POST',
    'https://data.oxylabs.io/v1/queries/batch',
    auth=('user', 'pass1'),
    json=payload,
)

# Print prettified response.
pprint(response.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

$paramsFile = file_get_contents(realpath("keywords.json"));
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://data.oxylabs.io/v1/queries/batch");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $paramsFile);
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.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

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


            var content = File.ReadAllText(@"C:\path\to\keywords.json");
                
            var client = new HttpClient();

            var requestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri("https://data.oxylabs.io/v1/queries/batch"));
            requestMessage.Content = new StringContent(content, Encoding.UTF8, "application/json");


            var authenticationString = $"{Username}:{Password}";
            var base64EncodedAuthenticationString = Convert.ToBase64String(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"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
)

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

	content, err := os.ReadFile("keywords.json")
	if err != nil {
		panic(err)
	}

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

	request.Header.Add("Content-type", "application/json")
	request.SetBasicAuth(Username, Password)
	response, _ := client.Do(request)

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

{% endtab %}

{% tab title="Java" %}

```java
import okhttp3.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

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() {
        Path filePath = Path.of("/path/to/keywords.json");
        String jsonContent = null;
        try {
            jsonContent = Files.readString(filePath);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        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(jsonContent, mediaType);
        var request = new Request.Builder()
                .url("https://data.oxylabs.io/v1/queries/batch")
                .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';
import fs from 'fs'

const username = 'YOUR_USERNAME';
const password = 'YOUR_PASSWORD';

const payload = fs.readFileSync('keywords.json').toString();

const response = await fetch('https://data.oxylabs.io/v1/queries/batch', {
  method: 'post',
  body: payload,
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + Buffer.from(`${username}:${password}`).toString('base64'),
  }
});

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

{% endtab %}
{% endtabs %}

Es posible que notes que el ejemplo de código anterior no explica cómo debe formatearse la carga útil JSON y señala un archivo JSON predefinido. A continuación se muestra el contenido de `keywords.json` archivo, que contiene múltiples `consulta` valores de parámetros:

```json
{  
   "query":[  
      "adidas",
      "nike",
      "reebok"
   ],
   "source": "google_shopping_search",
   "callback_url": "https://your.callback.url"
}
```

...y aquí hay un `keywords.json` archivo de entrada por lotes, que contiene múltiples URLs:

```json
{  
   "url":[  
      "https://example.com/url1.html",
      "https://example.com/url2.html",
      "https://example.com/url3.html"
   ],
   "source": "universal",
   "callback_url": "https://your.callback.url"
}
```

### Salida

La API responderá con un objeto JSON que contiene la información del trabajo para cada trabajo creado. La respuesta será similar a esta:

```json
{
  "queries": [
    {
      "callback_url": "https://your.callback.url",
      "created_at": "2026-09-03 00:00:01",
      "id": "12345678900987654321",
      "query": "adidas",
      "source": "google_shopping_search",
      "status": "pending",
      {...}
      "_links": [
        {
          "rel": "self",
          "href": "http://data.oxylabs.io/v1/queries/12345678900987654321",
          "method": "GET"
        },
        {
          "rel": "results",
          "href": "http://data.oxylabs.io/v1/queries/12345678900987654321/results",
          "method": "GET"
        },
        {...}
      ]
    },
    {
      "callback_url": "https://your.callback.url",
      "created_at": "2026-09-03 00:00:01",
      "id": "12345678901234567890",
      "query": "nike",
      "source": "google_shopping_search",
      "status": "pending",
      {...}
      "_links": [
        {
          "rel": "self",
          "href": "http://data.oxylabs.io/v1/queries/12345678901234567890",
          "method": "GET"
        },
        {
          "rel": "results",
          "href": "http://data.oxylabs.io/v1/queries/12345678901234567890/results",
          "method": "GET"
        },
        {...}
      ]
    },
    {
      "callback_url": "https://your.callback.url",
      "created_at": "2026-09-03 00:00:01",
      "id": "01234567899876543210",
      "query": "reebok",
      "source": "google_shopping_search",
      "status": "pending",
      {...}
      "_links": [
        {
          "rel": "self",
          "href": "http://data.oxylabs.io/v1/queries/01234567899876543210",
          "method": "GET"
        },
        {
          "rel": "results",
          "href": "http://data.oxylabs.io/v1/queries/01234567899876543210/results",
          "method": "GET"
        },
        {...}
      ]
    }
  ]
}
```

{% hint style="info" %}
Cada entrada contiene los mismos campos que una respuesta de trabajo individual; `{...}` indica los campos omitidos aquí por brevedad.
{% endhint %}

## Obtener la lista de direcciones IP del notificador

Es posible que quieras incluir en la lista blanca las IPs que te envían mensajes de callback o obtener la lista de estas IPs para otros fines. Puedes hacerlo `GET`consultando este endpoint:

### Punto final

```
GET https://data.oxylabs.io/v1/info/callbacker_ips
```

### Entrada

Los ejemplos de código siguientes muestran cómo puedes acceder a `/callbacker_ips` endpoint:

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

```bash
curl --user "USERNAME:PASSWORD" \\
'https://data.oxylabs.io/v1/info/callbacker_ips'
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
from pprint import pprint

# Get response from the callback IPs endpoint.
response = requests.request(
    method='GET',
    url='https://data.oxylabs.io/v1/info/callbacker_ips',
    auth=('user', 'pass1'),
)

# Print prettified JSON response to stdout.
pprint(response.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://data.oxylabs.io/v1/info/callbacker_ips");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_USERPWD, "user" . ":" . "pass1");

$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.Net.Http;
using System.Threading.Tasks;

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

            var client = new HttpClient();

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

            var requestMessage = new HttpRequestMessage(HttpMethod.Get, "/v1/info/callbacker_ips");

            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 (
	"fmt"
	"io/ioutil"
	"net/http"
)

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

	client := &http.Client{}
	request, _ := http.NewRequest("GET",
		"https://data.oxylabs.io/v1/info/callbacker_ips",
		nil,
	)

	request.Header.Add("Content-type", "application/json")
	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.*;

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() {
        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 request = new Request.Builder()
                .url("https://data.oxylabs.io/v1/info/callbacker_ips")
                .get()
                .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 response = await fetch('https://data.oxylabs.io/v1/info/callbacker_ips', {
  method: 'get',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + Buffer.from(`${username}:${password}`).toString('base64'),
  }
});

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

{% endtab %}
{% endtabs %}

### Salida

La API devolverá la lista de IPs que realizan solicitudes de callback a tu sistema:

```json
{
    "ips": [
        "x.x.x.x",
        "y.y.y.y"
    ]
}
```

## Scheduler

Scheduler es un servicio que puedes usar para programar trabajos de scraping recurrentes.

Amplía la funcionalidad de la integración Push-Pull y se usa mejor junto con la [**integración en la nube**](/products/es/web-scraper-api/features/result-processing-and-storage/cloud-storage.md) funcionalidad.

Visita esta página para aprender cómo usar la función Scheduler:

{% content-ref url="/pages/6747f0c229023ce8f8bd1f628917a02e8975721e" %}
[Scheduler](/products/es/web-scraper-api/features/scheduler.md)
{% endcontent-ref %}


---

# 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/integration-methods/push-pull.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.
