Vision

Запуск и остановка профилей

Введение

Vision предоставляет возможность запуска и остановки профилей по API, используя HTTP-запросы. Для отправки некоторых запросов может потребоваться X-Token, подробнее о нём можно прочитать в соответствующей статье.

Работа с профилями

Получение списка запущенных профилей

В Vision есть возможность получения информации по уже запущенным профилям.

Запрос

Для получения списка запущенных профилей необходимо отправить соответствующий GET запрос:

GET
http://127.0.0.1:3030/list

Пример запроса

const url =  "http://127.0.0.1:3030/list"; const options = {  method: "GET",  headers: {    "X-Token": "Your Token",   }, };fetch(url, options)  .then((response) => {    response.json().then((data) => {      console.log(data);    });  })  .catch((error) => {    console.error(error);  });
import requestsurl = 'http://127.0.0.1:3030/list' headers = {    'X-Token': 'Your Token',    'Content-Type': 'application/json'}response = requests.get(url, headers=headers)print(response.json())
<?php$url = "http://127.0.0.1:3030/list";$token = "Your Token"; $headers = array(  'X-Token: '.$token,  'Content-Type: application/json');$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);$data = curl_exec($ch);if (curl_errno($ch)) {    print "Error: " . curl_error($ch);} else {    var_dump($data);    curl_close($ch);}?>
// Requires tokio with features = ["macros", "rt-multi-thread"]// Requires reqwest with features = ["json"]// Requires serde_json#[tokio::main]async fn main() {    let url = "http://127.0.0.1:3030/list";    let token = "Token";     let client = reqwest::Client::new();    let response = client        .get(url)        .header("X-Token", token)        .send()        .await        .expect("Failed to send request")        .json::<serde_json::Value>()        .await        .expect("Failed to parse response");    dbg!(response);}
package mainimport (	"io"	"net/http")func main() {	url := "http://127.0.0.1:3030/list"	token := "Your Token"    	client := http.Client{}	req, err := http.NewRequest("GET", url, nil)	if err != nil {		panic(err)	}	req.Header.Add("X-Token", token)        	resp, err := client.Do(req)	if err != nil {		panic(err)	}	defer resp.Body.Close()	body, _ := io.ReadAll(resp.Body)	println(string(body))}
var url = "http://127.0.0.1:3030/list";var token = "Your Token"; var client = new HttpClient();client.DefaultRequestHeaders.Add("X-Token", token);var response = await client.GetAsync(url);var content = await response.Content.ReadAsStringAsync();Console.WriteLine(content);

Пример ответа

{
"profiles": [
    {
        "folder_id": "698d2698-11a5-4768-bfb8-92b904026bfd",
        "profile_id": "05296821-1ee5-445c-805f-1523578e898c",
        "port": null
    },
    {
        "folder_id": "698d2698-11a5-4768-bfb8-92b904026bfd",
        "profile_id": "98bc0cb8-3cae-483f-bb8c-2607cc5c9883",
        "port": null
    },
    {
        "folder_id": "698d2698-11a5-4768-bfb8-92b904026bfd",
        "profile_id": "9c6ed4a3-20b3-441d-adc6-58b99791f67b",
        "port": null
    }
]
}

Запуск профиля по API

Запрос

Для запуска профиля необходимо отправить соответствующий GET запрос:

Обратите внимание, что в URL запроса неободимо передать ID папки - folderId, в которой находится запускаемый профиль, а также ID самого профиля - profileID.

GET
http://127.0.0.1:3030/start/{folderId}/{profileId}
POST
http://127.0.0.1:3030/start/{folderId}/{profileId}

Если вы хотите передать дополнительные аргументы в браузер, вы можете сделать это, отправив POST запрос с JSON телом, содержащим поле args с массивом аргументов.

Заголовки запроса

Prop

Type

Тело запроса (необязательно)

Prop

Type

Пример запроса

const url =  "http://127.0.0.1:3030/start/{folderId}/{profileId}"; const options = {  method: "GET",  headers: {    "X-Token": "Your Token",   }, };fetch(url, options)  .then((response) => {    response.json().then((data) => {      console.log(data);    });  })  .catch((error) => {    console.error(error);  });
import requestsurl = 'http://127.0.0.1:3030/start/{folderId}/{profileId}' headers = {    'X-Token': 'Your Token',    'Content-Type': 'application/json'}response = requests.get(url, headers=headers)print(response.json())
<?php$url = "http://127.0.0.1:3030/start/{folderId}/{profileId}";$token = "Your Token"; $headers = array(  'X-Token: '.$token,  'Content-Type: application/json');$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);$data = curl_exec($ch);if (curl_errno($ch)) {    print "Error: " . curl_error($ch);} else {    var_dump($data);    curl_close($ch);}?>
// Requires tokio with features = ["macros", "rt-multi-thread"]// Requires reqwest with features = ["json"]// Requires serde_json#[tokio::main]async fn main() {    let url = "http://127.0.0.1:3030/start/{folderId}/{profileId}";    let token = "Token";     let client = reqwest::Client::new();    let response = client        .get(url)        .header("X-Token", token)        .send()        .await        .expect("Failed to send request")        .json::<serde_json::Value>()        .await        .expect("Failed to parse response");    dbg!(response);}
package mainimport (	"io"	"net/http")func main() {	url := "http://127.0.0.1:3030/start/{folderId}/{profileId}"	token := "Your Token"    	client := http.Client{}	req, err := http.NewRequest("GET", url, nil)	if err != nil {		panic(err)	}	req.Header.Add("X-Token", token)        	resp, err := client.Do(req)	if err != nil {		panic(err)	}	defer resp.Body.Close()	body, _ := io.ReadAll(resp.Body)	println(string(body))}
var url = "http://127.0.0.1:3030/start/{folderId}/{profileId}";var token = "Your Token"; var client = new HttpClient();client.DefaultRequestHeaders.Add("X-Token", token);var response = await client.GetAsync(url);var content = await response.Content.ReadAsStringAsync();Console.WriteLine(content);

Пример запроса запуска профиля в режиме headless

const url =  "http://127.0.0.1:3030/start/{folderId}/{profileId}"; const body = {  "args": [    "--headless"  ]}const options = {  method: "POST",  headers: {    "X-Token": "Your Token",     "Content-Type": "application/json"  },   body: JSON.stringify(body)};fetch(url, options)  .then((response) => {    response.json().then((data) => {      console.log(data);    });  })  .catch((error) => {    console.error(error);  });
import requestsurl = 'http://127.0.0.1:3030/start/{folderId}/{profileId}' body = {  "args": [    "--headless"  ]}headers = {    'X-Token': 'Your Token',    'Content-Type': 'application/json'}response = requests.post(url, headers=headers, json=body)print(response.json())
<?php$url = "http://127.0.0.1:3030/start/{folderId}/{profileId}";$token = "Your Token"; $body = '{  "args": [    "--headless"  ]}';$headers = array(  'X-Token: '.$token,  'Content-Type: application/json');$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);curl_setopt($ch, CURLOPT_POSTFIELDS, $body);$data = curl_exec($ch);if (curl_errno($ch)) {    print "Error: " . curl_error($ch);} else {    var_dump($data);    curl_close($ch);}?>
// Requires tokio with features = ["macros", "rt-multi-thread"]// Requires reqwest with features = ["json"]// Requires serde_json#[tokio::main]async fn main() {    let url = "http://127.0.0.1:3030/start/{folderId}/{profileId}";    let token = "Token";     let body = serde_json::json!(        {          "args": [            "--headless"          ]        }	);    let client = reqwest::Client::new();    let response = client        .post(url)        .header("X-Token", token)        .json(&body)        .send()        .await        .expect("Failed to send request")        .json::<serde_json::Value>()        .await        .expect("Failed to parse response");    dbg!(response);}
package mainimport (	"bytes"	"io"	"net/http")func main() {	url := "http://127.0.0.1:3030/start/{folderId}/{profileId}"	token := "Your Token"    body := []byte(`        {          "args": [            "--headless"          ]        }	`)	client := http.Client{}	req, err := http.NewRequest("POST", url, nil)	if err != nil {		panic(err)	}	req.Header.Add("X-Token", token)    req.Header.Add("Content-Type", "application/json")    req.Body = io.NopCloser(bytes.NewReader(body))	resp, err := client.Do(req)	if err != nil {		panic(err)	}	defer resp.Body.Close()	body, _ := io.ReadAll(resp.Body)	println(string(body))}
var url = "http://127.0.0.1:3030/start/{folderId}/{profileId}";var token = "Your Token"; var body = """{  "args": [    "--headless"  ]}"""var client = new HttpClient();client.DefaultRequestHeaders.Add("X-Token", token);client.DefaultRequestHeaders.Add("Content-Type", "application/json");var contentBody = new StringContent(body, Encoding.UTF8, "application/json");var response = await client.PostAsync(url, contentBody);var content = await response.Content.ReadAsStringAsync();Console.WriteLine(content);

Пример запроса запуска профиля с конкретным портом

В указанном ниже примере вместо PORT_NUMBER_HERE необходимо указать целое число в диапазоне от 1024 до 65535. Таким образом профиль будет запущен с указанным в коде портом, а вы сможете использовать именно этот порт для подключения к инстансу браузерного профиля.

const url =  "http://127.0.0.1:3030/start/{folderId}/{profileId}"; const body = {  "args": [    "--remote-debugging-port=PORT_NUMBER_HERE"  ]}const options = {  method: "POST",  headers: {    "X-Token": "Your Token",     "Content-Type": "application/json"  },   body: JSON.stringify(body)};fetch(url, options)  .then((response) => {    response.json().then((data) => {      console.log(data);    });  })  .catch((error) => {    console.error(error);  });
import requestsurl = 'http://127.0.0.1:3030/start/{folderId}/{profileId}' body = {  "args": [    "--remote-debugging-port=PORT_NUMBER_HERE"  ]}headers = {    'X-Token': 'Your Token',    'Content-Type': 'application/json'}response = requests.post(url, headers=headers, json=body)print(response.json())
<?php$url = "http://127.0.0.1:3030/start/{folderId}/{profileId}";$token = "Your Token"; $body = '{  "args": [    "--remote-debugging-port=PORT_NUMBER_HERE"  ]}';$headers = array(  'X-Token: '.$token,  'Content-Type: application/json');$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);curl_setopt($ch, CURLOPT_POSTFIELDS, $body);$data = curl_exec($ch);if (curl_errno($ch)) {    print "Error: " . curl_error($ch);} else {    var_dump($data);    curl_close($ch);}?>
// Requires tokio with features = ["macros", "rt-multi-thread"]// Requires reqwest with features = ["json"]// Requires serde_json#[tokio::main]async fn main() {    let url = "http://127.0.0.1:3030/start/{folderId}/{profileId}";    let token = "Token";     let body = serde_json::json!(        {          "args": [            "--remote-debugging-port=PORT_NUMBER_HERE"          ]        }	);    let client = reqwest::Client::new();    let response = client        .post(url)        .header("X-Token", token)        .json(&body)        .send()        .await        .expect("Failed to send request")        .json::<serde_json::Value>()        .await        .expect("Failed to parse response");    dbg!(response);}
package mainimport (	"bytes"	"io"	"net/http")func main() {	url := "http://127.0.0.1:3030/start/{folderId}/{profileId}"	token := "Your Token"    body := []byte(`        {          "args": [            "--remote-debugging-port=PORT_NUMBER_HERE"          ]        }	`)	client := http.Client{}	req, err := http.NewRequest("POST", url, nil)	if err != nil {		panic(err)	}	req.Header.Add("X-Token", token)    req.Header.Add("Content-Type", "application/json")    req.Body = io.NopCloser(bytes.NewReader(body))	resp, err := client.Do(req)	if err != nil {		panic(err)	}	defer resp.Body.Close()	body, _ := io.ReadAll(resp.Body)	println(string(body))}
var url = "http://127.0.0.1:3030/start/{folderId}/{profileId}";var token = "Your Token"; var body = """{  "args": [    "--remote-debugging-port=PORT_NUMBER_HERE"  ]}"""var client = new HttpClient();client.DefaultRequestHeaders.Add("X-Token", token);client.DefaultRequestHeaders.Add("Content-Type", "application/json");var contentBody = new StringContent(body, Encoding.UTF8, "application/json");var response = await client.PostAsync(url, contentBody);var content = await response.Content.ReadAsStringAsync();Console.WriteLine(content);

Пример запроса запуска профиля с временной прокси

Если необходимо запустить профиль с временной прокси, то можно указать данные от прокси в теле запроса на запуск. При этом данная прокси сохранена не будет. От вас потребуется передать в body запроса следующие данные:

  • тип прокси (http, https, socks5, ssh)
  • хост прокси (IP адрес или домен)
  • порт
  • логин (при наличии)
  • пароль (при наличии)

ВАЖНО: Для запуска профиля с временной прокси параметр args должен быть передан в любом случае.

Если аргументы есть — укажите их в массиве.

Если аргументов нет — передайте пустой массив (args: []), иначе запуск не выполнится.

const url =  "http://127.0.0.1:3030/start/{folderId}/{profileId}"; const body = {  "args": [],  "proxy": {    "type": "socks5",    "address": "1.1.1.1",    "port": 4123,    "username": "vision",    "password": "password"  }}const options = {  method: "POST",  headers: {    "X-Token": "Your Token",     "Content-Type": "application/json"  },   body: JSON.stringify(body)};fetch(url, options)  .then((response) => {    response.json().then((data) => {      console.log(data);    });  })  .catch((error) => {    console.error(error);  });
import requestsurl = 'http://127.0.0.1:3030/start/{folderId}/{profileId}' body = {  "args": [],  "proxy": {    "type": "socks5",    "address": "1.1.1.1",    "port": 4123,    "username": "vision",    "password": "password"  }}headers = {    'X-Token': 'Your Token',    'Content-Type': 'application/json'}response = requests.post(url, headers=headers, json=body)print(response.json())
<?php$url = "http://127.0.0.1:3030/start/{folderId}/{profileId}";$token = "Your Token"; $body = '{  "args": [],  "proxy": {    "type": "socks5",    "address": "1.1.1.1",    "port": 4123,    "username": "vision",    "password": "password"  }}';$headers = array(  'X-Token: '.$token,  'Content-Type: application/json');$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);curl_setopt($ch, CURLOPT_POSTFIELDS, $body);$data = curl_exec($ch);if (curl_errno($ch)) {    print "Error: " . curl_error($ch);} else {    var_dump($data);    curl_close($ch);}?>
// Requires tokio with features = ["macros", "rt-multi-thread"]// Requires reqwest with features = ["json"]// Requires serde_json#[tokio::main]async fn main() {    let url = "http://127.0.0.1:3030/start/{folderId}/{profileId}";    let token = "Token";     let body = serde_json::json!(        {          "args": [],          "proxy": {            "type": "socks5",            "address": "1.1.1.1",            "port": 4123,            "username": "vision",            "password": "password"          }        }	);    let client = reqwest::Client::new();    let response = client        .post(url)        .header("X-Token", token)        .json(&body)        .send()        .await        .expect("Failed to send request")        .json::<serde_json::Value>()        .await        .expect("Failed to parse response");    dbg!(response);}
package mainimport (	"bytes"	"io"	"net/http")func main() {	url := "http://127.0.0.1:3030/start/{folderId}/{profileId}"	token := "Your Token"    body := []byte(`        {          "args": [],          "proxy": {            "type": "socks5",            "address": "1.1.1.1",            "port": 4123,            "username": "vision",            "password": "password"          }        }	`)	client := http.Client{}	req, err := http.NewRequest("POST", url, nil)	if err != nil {		panic(err)	}	req.Header.Add("X-Token", token)    req.Header.Add("Content-Type", "application/json")    req.Body = io.NopCloser(bytes.NewReader(body))	resp, err := client.Do(req)	if err != nil {		panic(err)	}	defer resp.Body.Close()	body, _ := io.ReadAll(resp.Body)	println(string(body))}
var url = "http://127.0.0.1:3030/start/{folderId}/{profileId}";var token = "Your Token"; var body = """{  "args": [],  "proxy": {    "type": "socks5",    "address": "1.1.1.1",    "port": 4123,    "username": "vision",    "password": "password"  }}"""var client = new HttpClient();client.DefaultRequestHeaders.Add("X-Token", token);client.DefaultRequestHeaders.Add("Content-Type", "application/json");var contentBody = new StringContent(body, Encoding.UTF8, "application/json");var response = await client.PostAsync(url, contentBody);var content = await response.Content.ReadAsStringAsync();Console.WriteLine(content);

Обратите внимание, что временная прокси является приоритетным выбором при запуске.

Это значит, что при наличии у профиля привязанной прокси, запуск всё равно произойдёт с временной прокси.

Ответ

Данные ответа

Prop

Type

Пример ответа

{
"folder_id": "698d2698-11a5-4768-bfb8-92b904026bfd",
"profile_id": "98bc0cb8-3cae-483f-bb8c-2607cc5c9883",
"port": 19512
}

Остановка профиля по API

Запрос

Для остановки профиля необходимо отправить соответствующий GET запрос:

GET
http://127.0.0.1:3030/stop/{folderId}/{profileId}

Обратите внимание, что в URL запроса необходимо передать ID папки - folderId, в которой находится останавливаемый профиль, а также ID самого профиля - profileId.

Пример запроса

const url =  "http://127.0.0.1:3030/stop/{folderId}/{profileId}"; const options = {  method: "GET",  headers: {    "X-Token": "Your Token",   }, };fetch(url, options)  .then((response) => {    response.json().then((data) => {      console.log(data);    });  })  .catch((error) => {    console.error(error);  });
import requestsurl = 'http://127.0.0.1:3030/stop/{folderId}/{profileId}' headers = {    'X-Token': 'Your Token',    'Content-Type': 'application/json'}response = requests.get(url, headers=headers)print(response.json())
<?php$url = "http://127.0.0.1:3030/stop/{folderId}/{profileId}";$token = "Your Token"; $headers = array(  'X-Token: '.$token,  'Content-Type: application/json');$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);$data = curl_exec($ch);if (curl_errno($ch)) {    print "Error: " . curl_error($ch);} else {    var_dump($data);    curl_close($ch);}?>
// Requires tokio with features = ["macros", "rt-multi-thread"]// Requires reqwest with features = ["json"]// Requires serde_json#[tokio::main]async fn main() {    let url = "http://127.0.0.1:3030/stop/{folderId}/{profileId}";    let token = "Token";     let client = reqwest::Client::new();    let response = client        .get(url)        .header("X-Token", token)        .send()        .await        .expect("Failed to send request")        .json::<serde_json::Value>()        .await        .expect("Failed to parse response");    dbg!(response);}
package mainimport (	"io"	"net/http")func main() {	url := "http://127.0.0.1:3030/stop/{folderId}/{profileId}"	token := "Your Token"    	client := http.Client{}	req, err := http.NewRequest("GET", url, nil)	if err != nil {		panic(err)	}	req.Header.Add("X-Token", token)        	resp, err := client.Do(req)	if err != nil {		panic(err)	}	defer resp.Body.Close()	body, _ := io.ReadAll(resp.Body)	println(string(body))}
var url = "http://127.0.0.1:3030/stop/{folderId}/{profileId}";var token = "Your Token"; var client = new HttpClient();client.DefaultRequestHeaders.Add("X-Token", token);var response = await client.GetAsync(url);var content = await response.Content.ReadAsStringAsync();Console.WriteLine(content);

Ответ

Пример ответа

Stopping profile 98bc0cb8-3cae-483f-bb8c-2607cc5c9883 in folder 698d2698-11a5-4768-bfb8-92b904026bfd

На этой странице