# Push-Pull

Push-Pull es nuestro método de integración recomendado para manejar de forma fiable grandes cantidades 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).&#x20;
{% endhint %}

Push-Pull es un método de integración asíncrono. Al enviar el trabajo, recibirás de inmediato un `JSON` respuesta que contiene todos los detalles del trabajo, incluidos los parámetros del trabajo, el ID y las URL para descargar el resultado y comprobar el estado. Una vez procesado tu trabajo, te avisaremos mediante un `JSON` payload enviado a tu servidor, si proporcionaste una URL de [**callback**](#callback) . Los resultados permanecen disponibles para su recuperación durante **al menos 24 horas** después de finalizar.

Con Push-Pull, puedes subir tus resultados directamente a 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 las notificaciones entrantes de callback, puedes simplemente recuperar tus resultados periódicamente (*sondeo*).
{% endhint %}

También puedes explorar cómo funciona Push-Pull usando [**Postman**](broken://spaces/P91ya1mpAK3bvuNKJQ1c/pages/7e1f7b8481bad4953687471a9a04f5dc5ac6b686).

## Trabajo único

### Endpoint

Este endpoint acepta solo un único `query` 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 "user:pass1" \\
'https://data.oxylabs.io/v1/queries' \\
-H "Content-Type: application/json" \
 -d '{"source": "ENTER_SOURCE_HERE", "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


# Structure payload.
payload = {
    "source": "ENTER_SOURCE_HERE", # Source you choose e.g. "universal"
    "url": "https://www.example.com", # Check speficic source if you should use "url" or "query"
    "geo_location": "United States", # Some sources accept zip-code or cooprdinates
    #"render" : "html", # Uncomment you want to render JavaScript within the page
    #"render" : "png", # Uncomment if you want to take a screenshot of a scraped web page
    #"parse" : true, # Check what sources support parsed data
    #"callback_url": "https://your.callback.url", #required if using callback listener
    "callback_url": "https://your.callback.url",
    "storage_type": "s3", 
    "storage_url": "s3://your.storage.bucket.url"
}

# Get response.
response = requests.request(
    'POST',
    'https://data.oxylabs.io/v1/queries',
    auth=('YOUR_USERNAME', 'YOUR_PASSWORD'), #Your credentials go here
    json=payload,
)

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

{% endtab %}

{% tab title="PHP" %}

```php
<?php

$params = array(
    'source' => 'ENTER_SOURCE_HERE', //Source you choose e.g. "universal"
    'url' => 'https://www.example.com', // Check speficic source if you should use "url" or "query"
    'geo_location' => 'United States', //Some sources accept zip-code or cooprdinates
    //'render' : 'html', // Uncomment you want to render JavaScript within the page
    //'render' : 'png', // Uncomment if you want to take a screenshot of a scraped web page
    //'parse' : TRUE, // Check what sources support parsed data
    //'callback_url' => 'https://your.callback.url', //required if using callback listener
    'callback_url': 'https://your.callback.url',
    '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"); //Your credentials go here

$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", "ENTER_SOURCE_HERE" },
                { "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": "ENTER_SOURCE_HERE",
		"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", "ENTER_SOURCE_HERE");
        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" %}

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

const username = 'YOUR_USERNAME';
const password = 'YOUR_PASSWORD';
const body = {
  source: 'ENTER_SOURCE_HERE',
  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": [
    {
      "key": "results_language",
      "value": null
    },
    {
      "key": "safe_search",
      "value": null
    },
    {
      "key": "tbm",
      "value": null
    },
    {
      "key": "cr",
      "value": null
    },
    {
      "key": "filter",
      "value": null
    }
  ],
  "created_at": "2024-06-26 00:00:01",
  "geo_location": "United States",
  "id": "12345678900987654321",
  "limit": 10,
  "locale": null,
  "pages": 1,
  "parse": false,
  "render": null,
  "url": "https://www.example.com",
  "source": "universal",
  "start_page": 1,
  "status": "pending",
  "storage_type": "s3",
  "storage_url": "YOUR_BUCKET_NAME/12345678900987654321.json",
  "subdomain": "www",
  "updated_at": "2024-06-26 00:00:01",
  "user_agent_type": "desktop",
  "_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"
    }
  ]
}
```

### Diccionario de datos

Para descripciones detalladas de los parámetros de entrada del trabajo, consulta la tabla siguiente o las páginas de documentación específicas de los scrapers que te interesen.

| Clave              | Descripción                                                                                                                                                                                                                        | Tipo       |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `created_at`       | La fecha y hora en que se creó el trabajo.                                                                                                                                                                                         | Cadena     |
| `client_id`        | El ID numérico asociado con el nombre de usuario del cliente que realiza la solicitud.                                                                                                                                             | Cadena     |
| `client_notes`     | Notas enviadas por el cliente al enviar un trabajo.                                                                                                                                                                                | Cadena     |
| `content_encoding` | Añade este parámetro si estás descargando imágenes. Más información [**aquí**](/products/es/web-scraper-api/features/result-processing-and-storage/output-types/download-images.md)**.**                                           | Cadena     |
| `id`               | El ID único del trabajo.                                                                                                                                                                                                           | Cadena     |
| `estados`          | El código de estado del trabajo de scraping o parsing. Puedes ver los códigos de estado descritos [**aquí**](/products/es/web-scraper-api/response-codes.md).                                                                      | Entero     |
| `status`           | El estado del trabajo. `pending` significa que el trabajo aún se está procesando. `done` significa que hemos completado el trabajo. `faulted` significa que encontramos errores al intentar completar el trabajo y lo abandonamos. | Cadena     |
| `subdomain`        | El subdominio del sitio web.                                                                                                                                                                                                       | Cadena     |
| `updated_at`       | La fecha y hora en que se actualizó por última vez el trabajo. Para los trabajos que están finalizados (`status` es `done` o `faulted`), esta fecha y hora indica cuándo finalizó el trabajo.                                      | Cadena     |
| `enlaces`          | La lista de enlaces, relacionada con la entrada proporcionada.                                                                                                                                                                     | Array JSON |
| `enlaces`:`rel`    | El tipo de enlace. `self` La URL contiene los metadatos del trabajo, mientras que `resultados` La URL contiene los resultados del trabajo.                                                                                         | Cadena     |
| `enlaces`:`href`   | La URL del recurso.                                                                                                                                                                                                                | Cadena     |
| `enlaces`:`método` | El método HTTP que debe usarse para interactuar con una URL dada.                                                                                                                                                                  | Cadena     |

## Callback&#x20;

El callback es una `POST` solicitud que enviamos a tu máquina, informando que la tarea de extracción de datos ha finalizado 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 lo haremos saber, y todo lo que tienes que hacer ahora es [**recuperarlos**](#retrieve-job-content).

### Entrada

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

```python
# Este es un servidor web simple de Sanic 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 es asíncrono, pero las solicitudes son síncronas; para aprovechar
                # al máximo Sanic, usa 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" %}

```shell
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
{  
   "created_at":"2019-10-01 00:00:01",
   "updated_at":"2019-10-01 00:00:15",
   "locale":null,
   "client_id":163,
   "user_agent_type":"desktop",
   "source":"google_shopping_search",
   "pages":1,
   "subdomain":"www",
   "status":"done",
   "start_page":1,
   "parse":0,
   "render":null,
   "priority":0,
   "ttl":0,
   "origin":"api",
   "persist":true,
   "id":"12345678900987654321",
   "callback_url":"http://your.callback.url/",
   "query":"adidas",
   "limit":10,
   "geo_location":null,
   {...}
   "_links":[
      {  
         "href":"https://data.oxylabs.io/v1/queries/12345678900987654321",
         "method":"GET",
         "rel":"self"
      },
      {  
         "href":"https://data.oxylabs.io/v1/queries/12345678900987654321/results",
         "method":"GET",
         "rel":"results"
      }
   ],
}
```

## Comprobar el estado del trabajo

Si proporcionaste una URL de callback válida al enviar tu trabajo, te notificaremos cuando finalice enviando un `JSON` payload a la URL de callback especificada. Este payload indicará que el trabajo se ha completado y que su estado se ha establecido en `done`.

Sin embargo, si enviaste un trabajo sin usar [**servicio de callback**](#callback), puedes comprobar el estado del trabajo manualmente. Recupera la URL del `href` campo en la `sección rel:self` 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 `status`.

### Endpoint

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

### Entrada

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

```bash
curl --user "user:pass1" \\
'http://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='http://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, "http://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" %}

```shell
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 finalizar el trabajo, la API responderá con información de la consulta en formato JSON. El estado del trabajo cambiará a `done`, indicando que el trabajo ha finalizado. Puedes recuperar el contenido consultando uno de los enlaces proporcionados. Además, la respuesta incluirá la marca de tiempo de cuándo se actualizó por última vez el trabajo, lo que te permite seguir su tiempo de procesamiento.

```json
{
    "client_id": 5,
    "context": [
        {
            "key": "results_language",
            "value": null
        },
        {
            "key": "safe_search",
            "value": null
        },
        {
            "key": "tbm",
            "value": null
        },
        {
            "key": "cr",
            "value": null
        },
        {
            "key": "filter",
            "value": null
        }
    ],
    "created_at": "2019-10-01 00:00:01",
    "geo_location": null,
    "id": "7173957294344910849",
    "limit": 10,
    "locale": null,
    "pages": 1,
    "parse": false,
    "render": null,
    "query": "adidas",
    "source": "google_shopping_search",
    "start_page": 1,
    "status": "done",
    "subdomain": "www",
    "updated_at": "2019-10-01 00:00:15",
    "user_agent_type": "desktop",
    "_links": [
        {
            "rel": "self",
            "href": "http://data.oxylabs.io/v1/queries/7173957294344910849",
            "method": "GET"
        },
        {
            "rel": "results",
            "href": "http://data.oxylabs.io/v1/queries/7173957294344910849/results",
            "method": "GET"
        },
        {
            "rel": "results-html",
            "href": "http://data.oxylabs.io/v1/queries/7173957294344910849/results?type=raw",
            "method": "GET"
        },
        {
            "rel": "results-parsed",
            "href": "http://data.oxylabs.io/v1/queries/7173957294344910849/results?type=parsed",
            "method": "GET"
        },
        {
            "rel": "results-parsed",
            "href": "http://data.oxylabs.io/v1/queries/7173957294344910849/results?type=png",}
            "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 todavía se está procesando y no se ha completado.</td></tr><tr><td><code>done</code></td><td>El trabajo está completado. Puedes recuperar 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 te cobrará por ningún <code>faulted</code> trabajo.</td></tr></tbody></table>

## Recuperar contenido del trabajo

Una vez que el trabajo esté listo para ser recuperado, puedes usar la URL proporcionada en la respuesta bajo la `rel:results` sección. La URL se verá así: `http://data.oxylabs.io/v1/queries/7173957294344910849/results`.

### Endpoints

Puedes recuperar diferentes 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 puedes recuperar [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
```

### 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 "user:pass1" \\
'http://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='http://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, "http://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" %}

```shell
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 resultado predeterminado y otros tipos de resultado disponibles según los encabezados incluidos en la carga útil de la solicitud de la API.

| Parámetro de renderizado | Parámetro de parseo | Parámetro XHR | Salida predeterminada | Salida disponible |
| ------------------------ | ------------------- | ------------- | --------------------- | ----------------- |
| -                        | -                   | -             | html                  | html              |
| `html`                   | -                   | -             | html                  | html              |
| `html`                   | -                   | `true`        | xhr                   | html, xhr         |
| `html`                   | `true`              | `true`        | parsed                | html, xhr, parsed |
| `png`                    | -                   | -             | png                   | html, png         |
| -                        | `true`              | -             | parsed                | html, parsed      |
| `html`                   | `true`              | -             | parsed                | html, parsed      |
| `png`                    | `true`              | -             | png                   | html, parsed, png |

A continuación se muestra una respuesta de ejemplo del `/results` endpoint:

```json
{
  "results": [
    {
      "content": "<!doctype html><html>
        CONTENT      
      </html>",
      "created_at": "2019-10-01 00:00:01",
      "updated_at": "2019-10-01 00:00:15",
      "page": 1,
      "url": "https://www.google.com/search?q=adidas&hl=en&gl=US",
      "job_id": "12345678900987654321",
      "status_code": 200
    }
  ]
}
```

Los resultados se pueden recuperar automáticamente sin comprobar periódicamente el estado del trabajo configurando [**Callback**](#callback) el servicio. Para ello, especifica la URL de un servidor que pueda aceptar solicitudes HTTP(S) entrantes al enviar un trabajo. Cuando nuestro sistema complete el trabajo, `POST` un payload JSON a la URL proporcionada, y el servicio 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 `query` o `url` valores de parámetro en una sola solicitud por lotes.&#x20;

{% hint style="warning" %}
B**Las solicitudes por lotes** actualmente **no son compatibles** para `chatgpt` y `perplexity` fuentes.
{% endhint %}

### Endpoint

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

El sistema gestionará cada `query` o `url` enviado como un trabajo separado. Si proporcionas una URL de callback, recibirás una llamada separada para cada palabra clave. De lo contrario, nuestra respuesta inicial contendrá trabajos `id`para todas las palabras clave. Por ejemplo, si enviaste 50 palabras clave, devolveremos 50 trabajos únicos `id`.

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

### Entrada

Debes enviar los parámetros de consulta como un payload JSON. Así es como envías un trabajo por lotes:

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

```shell
curl --user "user:pass1" \\
'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


# Obtener el payload del archivo.
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" %}

```shell
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 %}

Puede que notes que el ejemplo de código anterior no explica cómo debe formatearse el payload JSON y señala un archivo JSON ya preparado. A continuación se muestra el contenido de `keywords.json` archivo, que contiene múltiples `query` valores de parámetro:

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

...y aquí tienes 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": "2019-10-01 00:00:01",
      "id": "12345678900987654321",
      {...}
      "query": "adidas",
      "source": "google_shopping_search",
      {...}
          "rel": "results",
          "href": "http://data.oxylabs.io/v1/queries/12345678900987654321/results",
          "method": "GET"
        }
      ]
    },
    {
      "callback_url": "https://your.callback.url",
      {...}
      "created_at": "2019-10-01 00:00:01",
      "id": "12345678901234567890",
      {...}
      "query": "nike",
      "source": "google_shopping_search",
      {...}
          "rel": "results",
          "href": "http://data.oxylabs.io/v1/queries/12345678901234567890/results",
          "method": "GET"
        }
      ]
    },
    {
      "callback_url": "https://your.callback.url",
      {...}
      "created_at": "2019-10-01 00:00:01",
      "id": "01234567899876543210",
	  {...}
      "query": "reebok",
      "source": "google_shopping_search",
	  {...}
          "rel": "results",
          "href": "http://data.oxylabs.io/v1/queries/01234567899876543210/results",
          "method": "GET"
        }
      ]
    }
  ]
}
```

## Obtener lista de direcciones IP del Notifier

Puede que quieras incluir en la lista blanca las IP que te envían mensajes de callback o obtener la lista de estas IP para otros fines. Puedes hacerlo `GET`consultando este endpoint:&#x20;

### Endpoint

```
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 "user:pass1" \\
'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" %}

```shell
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 IP 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.&#x20;

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

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: 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:

```
GET https://developers.oxylabs.io/products/es/web-scraper-api/integration-methods/push-pull.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
