gologin 2.1.18 → 2.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.json CHANGED
@@ -102,7 +102,7 @@
102
102
  ],
103
103
  "max-lines": [
104
104
  "warn",
105
- 1500
105
+ 2000
106
106
  ],
107
107
  "no-else-return": [
108
108
  "warn",
package/README.md CHANGED
@@ -1,103 +1,179 @@
1
- # class GoLogin - class for working with <a href="https://gologin.com" target="_blank">gologin.com</a> API
2
- # Official Package
1
+ # GoLogin Node.js SDK
2
+ This package provides functionality to run and stop GoLogin profiles with node.js and then connect the profiles to automation tools like Selenium, Puppetteer, Playwright etc.
3
3
 
4
- ## Getting Started
5
-
6
- GoLogin supports Linux, MacOS and Windows platforms.
4
+ # How does it work?
5
+ 1. You give SDK your dev token and profile id that you want to run
6
+ 2. SDK takes care of downloading, preparing your profile and starts the browser
7
+ 3. SDK gives you websocket url for automation tools
8
+ 4. You take this websocker url and connect it to the automation tool on your choice: Puppetteer, Selenium, Playwright etc
9
+ 5. Automation tool connects to browser and you can manage it through code
7
10
 
8
- ### Installation
9
-
10
- `npm i gologin`
11
+ ## Getting Started
11
12
 
12
- for running example.js install puppeteer-core
13
+ Where is token? API token is <a href="https://app.gologin.com/#/personalArea/TokenApi" target="_blank">here</a>.
13
14
 
14
- `npm i puppeteer-core`
15
+ ![Token API in Settings](https://user-images.githubusercontent.com/12957968/146891933-c3b60b4d-c850-47a5-8adf-bc8c37372664.gif)
15
16
 
16
- ### Usage
17
17
 
18
- Where is token? API token is <a href="https://app.gologin.com/#/personalArea/TokenApi" target="_blank">here</a>.
19
- To have an access to the page below you need <a href="https://app.gologin.com/#/createUser" target="_blank">register</a> GoLogin account.
18
+ ### Installation
20
19
 
21
- ![Token API in Settings](https://user-images.githubusercontent.com/12957968/146891933-c3b60b4d-c850-47a5-8adf-bc8c37372664.gif)
20
+ `npm i gologin`
22
21
 
23
22
  ### Example
24
23
 
25
24
  ```js
26
- import puppeteer from 'puppeteer-core';
25
+ import { GologinApi } from './src/gologin-api.js';
27
26
 
28
- import GoLogin from '../src/gologin.js';
27
+ const GL = GologinApi({
28
+ token: 'your token',
29
+ });
29
30
 
30
- const { connect } = puppeteer;
31
+ const profile = await GL.createProfileRandomFingerprint('some name');
32
+ const profileId = profile.id;
31
33
 
32
- (async () => {
33
- const GL = new GoLogin({
34
- token: 'yU0token',
35
- profile_id: 'yU0Pr0f1leiD',
36
- });
37
-
38
- const { status, wsUrl } = await GL.start().catch((e) => {
39
- console.trace(e);
34
+ await GL.addGologinProxyToProfile(profileId, 'us');
35
+ const browser = await GL.launch({ profileId });
36
+ const page = await browser.newPage();
37
+ await page.goto('https://linkedin.com');
38
+ await new Promise((resolve) => setTimeout(resolve, 5000));
39
+ await browser.close();
40
+ await GL.stop();
41
+ ```
40
42
 
41
- return { status: 'failure' };
42
- });
43
+ ###
44
+ ### Methods
45
+ #### constructor
43
46
 
44
- if (status !== 'success') {
45
- console.log('Invalid status');
47
+ Required options:
48
+ - `token` <[string]> **Required** - your API <a href="https://gologin.com/#/personalArea/TokenApi" target="_blank">token</a>
46
49
 
47
- return;
48
- }
50
+ Optional options:
51
+ - `profile_id` <[string]> - profile ID (NOT PROFILE NAME) will be generated if not specified
52
+ - `executablePath` <[string]> path to executable Orbita file. Orbita will be downloaded automatically if not specified
53
+ - `extra_params` arrayof <[string]> additional flags for browser start. For example: '--headles', '--load-extentions=path/to/extension'
54
+ - `uploadCookiesToServer` <[boolean]> upload cookies to server after profile stopping (default false). It allows you to export cookies from api later.
55
+ - `writeCookesFromServer` <[boolean]> if you have predefined cookies and you want browser to import it (default true).
56
+ - `tmpdir` <[string]> absolute path to the directtory where you want to store user-data-dir. Default path in tmp folder will be picked if no specified
57
+ - `vncPort` <[integer]> port of VNC server if you using it
49
58
 
50
- const browser = await connect({
51
- browserWSEndpoint: wsUrl.toString(),
52
- ignoreHTTPSErrors: true,
53
- });
59
+ ```js
60
+ const GL = new GoLogin({
61
+ token: 'your token',
62
+ profile_id: 'profile id',
63
+ extra_params: ["--headless", "--load-extentions=path/to/extension"]
64
+ });
65
+ ```
54
66
 
55
- const page = await browser.newPage();
56
- await page.goto('https://myip.link/mini');
57
- console.log(await page.content());
58
- await browser.close();
59
- await GL.stop();
60
- })();
67
+ #### createProfileRandomFingerprint - you pass os ('lin', 'win', 'mac') and profile name and we give you brand new shiny profile
68
+ ```js
69
+ const GL = new GoLogin({
70
+ token: 'your token',
71
+ profile_id: 'profile id',
72
+ extra_params: ["--headless", "--load-extentions=path/to/extension"]
73
+ });
74
+ const profile = await gl.createProfileRandomFingerprint("some name")
75
+ const profileId = profile.id
61
76
  ```
62
77
 
63
- ### Running example:
64
78
 
65
- `DEBUG=gologin* node example.js`
79
+ #### createProfileWithCustomParams - This method creates a profile and you can pass any particular params to it. Full list of params you can find here - https://api.gologin.com/docs
80
+ ```js
81
+ const GL = GoLogin({
82
+ "token": "your token",
83
+ })
84
+ const profile = await gl.createProfileWithCustomParams({
85
+ "os": "lin",
86
+ "name": "some name",
87
+ "navigator": {
88
+ "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
89
+ "resolution": "1920x1080",
90
+ "language": "en-US",
91
+ "platform": "Linux x86_64",
92
+ "hardwareConcurrency": 8,
93
+ "deviceMemory": 8,
94
+ "maxTouchPoints": 0
95
+ }
96
+ })
97
+ const profileId = profile.id
98
+ ```
66
99
 
67
- ###
68
- ### Methods
69
- #### constructor
100
+ #### updateUserAgentToLatestBrowser - user agent is one of the most important thing in your fingerprint. It decides which browser version to run. This method help you to keep useragent up to date.
101
+ ```js
102
+ const GL = GoLogin({
103
+ "token": "your token",
104
+ })
105
+ await GL.updateUserAgentToLatestBrowser(["profineId1", "profileId2"], "workspceId(optional)")
106
+ ```
70
107
 
71
- - `options` <[Object]> Options for profile
72
- - `autoUpdateBrowser` <[boolean]> do not ask whether download new browser version (default false)
73
- - `token` <[string]> your API <a href="https://gologin.com/#/personalArea/TokenApi" target="_blank">token</a>
74
- - `profile_id` <[string]> profile ID
75
- - `executablePath` <[string]> path to executable Orbita file. Orbita will be downloaded automatically if not specified.
76
- - `remote_debugging_port` <[int]> port for remote debugging
77
- - `vncPort` <[integer]> port of VNC server if you using it
78
- - `tmpdir` <[string]> path to temporary directore for saving profiles
79
- - `extra_params` arrayof <[string]> extra params for browser orbita (ex. extentions etc.)
80
- - `uploadCookiesToServer` <[boolean]> upload cookies to server after profile stopping (default false)
81
- - `writeCookesFromServer` <[boolean]> download cookies from server and write to profile cookies file (default true)
82
- - `skipOrbitaHashChecking` <[boolean]> skip hash checking for Orbita after downloading process (default false)
108
+ #### addGologinProxyToProfile - Gologin provides high quality proxies with free traffic for paid users. Here you can add gologin proxy to profile, just pass country code
109
+ ```js
110
+ const GL = GoLogin({
111
+ "token": "your token",
112
+ })
113
+ await GL.addGologinProxyToProfile("profileId", "us")
114
+ ```
83
115
 
116
+ #### addCookiesToProfile - You can pass cookies to the profile and browser will import it before starting
84
117
  ```js
85
- import GoLogin from '../src/gologin.js';
86
- const GL = new GoLogin({
87
- token: 'yU0token',
88
- profile_id: 'yU0Pr0f1leiD',
89
- });
118
+ const GL = GoLogin({
119
+ "token": "your token",
120
+ })
121
+
122
+ await GL.addCookiesToProfile("profileId", [
123
+ {
124
+ "name": "session_id",
125
+ "value": "abc123",
126
+ "domain": "example.com",
127
+ "path": "/",
128
+ "expirationDate": 1719161018.307793,
129
+ "httpOnly": True,
130
+ "secure": True
131
+ },
132
+ {
133
+ "name": "user_preferences",
134
+ "value": "dark_mode",
135
+ "domain": "example.com",
136
+ "path": "/settings",
137
+ "sameSite": "lax"
138
+ }
139
+ ])
140
+ ```
141
+
142
+ #### refreshProfilesFingerprint - Replaces your profile fingerprint with a new one
143
+ ```js
144
+ const GL = GoLogin({
145
+ "token": "your token",
146
+ })
147
+
148
+ await GL.refreshProfilesFingerprint(["profileId1", "profileId2"])
90
149
  ```
91
150
 
92
- #### start()
151
+ #### changeProfileProxy - allows you to set a proxy to a profile
152
+ ```js
153
+ const GL = GoLogin({
154
+ "token": "your token",
155
+ })
156
+ await GL.changeProfileProxy("profileId", { "mode": "http", "host": "somehost.com", "port": 109, "username": "someusername", "password": "somepassword"})
157
+ ```
93
158
 
94
- - returns: <[object]> { status, wsUrl }
159
+ #### launch() - starts browser with profile id, returning WebSocket url for puppeteer
160
+ ```js
161
+ const GL = GoLogin({
162
+ "token": "your token",
163
+ })
164
+ await GL.launch({ profileId: 'some profileId' })
165
+ ```
95
166
 
96
- start browser with profile id, returning WebSocket url for puppeteer
97
167
 
98
- #### stop()
168
+ #### exit() stops browser and uploads it to the storage
169
+ ```js
170
+ const GL = GoLogin({
171
+ "token": "your token",
172
+ })
173
+ await GL.launch({ profileId: 'some profileId' })
174
+ await GL.exit()
175
+ ```
99
176
 
100
- stop browser with profile id
101
177
 
102
178
  ### DEBUG
103
179
 
package/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { type Browser } from 'puppeteer-core/lib/Browser';
2
2
 
3
+ import { CreateCustomBrowserValidation, BrowserProxyCreateValidation } from './types/profile-params';
4
+
3
5
  export const OPERATING_SYSTEMS = {
4
6
  win: 'win',
5
7
  lin: 'lin',
@@ -45,12 +47,29 @@ type LaunchParams =
45
47
  os: OsType;
46
48
  };
47
49
 
48
- type LaunchFn = (params?: LaunchParams) => Promise<{ browser: Browser }>;
50
+ type Cookie = {
51
+ name: string;
52
+ value: string;
53
+ domain: string;
54
+ path: string;
55
+ expirationDate?: number;
56
+ creationDate?: number;
57
+ hostOnly?: boolean;
58
+ httpOnly?: boolean;
59
+ sameSite?: 'no_restriction' | 'lax' | 'strict';
60
+ secure?: boolean;
61
+ session?: boolean;
62
+ url?: string;
63
+ };
49
64
 
50
65
  type GologinApiType = {
51
- launch: LaunchFn;
66
+ launch: (params?: LaunchParams) => Promise<{ browser: Browser }>;
52
67
  exit: (status = 0) => Promise<void>;
53
- delay: (ms: number) => Promise<void>;
68
+ createCustom: (params: CreateCustomBrowserValidation) => Promise<string>;
69
+ updateProfileFingerprint: (profileId: string[]) => Promise<void>;
70
+ updateUserAgentToLatestBrowser: (profileIds: string[], workspaceId?: string) => Promise<void>;
71
+ updateProfileProxy: (profileId: string, proxyData: BrowserProxyCreateValidation) => Promise<void>;
72
+ addCookiesToProfile: (profileId: string, cookies: Cookie[]) => Promise<void>;
54
73
  };
55
74
 
56
75
  type GologinApiParams = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gologin",
3
- "version": "2.1.18",
3
+ "version": "2.1.20",
4
4
  "description": "A high-level API to control Orbita browser over GoLogin API",
5
5
  "types": "./index.d.ts",
6
6
  "main": "./src/gologin.js",
@@ -1,17 +1,19 @@
1
1
  import puppeteer from 'puppeteer-core';
2
2
 
3
3
  import GoLogin from './gologin.js';
4
+ import { API_URL, getOsAdvanced } from './utils/common.js';
4
5
 
5
- export function getDefaultParams() {
6
- return {
7
- token: process.env.GOLOGIN_API_TOKEN,
8
- profile_id: process.env.GOLOGIN_PROFILE_ID,
9
- executablePath: process.env.GOLOGIN_EXECUTABLE_PATH,
10
- autoUpdateBrowser: true,
11
- };
12
- }
6
+ const trafficLimitMessage =
7
+ 'You dont have free traffic to use the proxy. Please go to app https://app.gologin.com/ and buy some traffic if you want to use the proxy';
13
8
 
14
- const createLegacyGologin = ({ profileId, ...params }) => {
9
+ export const getDefaultParams = () => ({
10
+ token: process.env.GOLOGIN_API_TOKEN,
11
+ profile_id: process.env.GOLOGIN_PROFILE_ID,
12
+ executablePath: process.env.GOLOGIN_EXECUTABLE_PATH,
13
+ autoUpdateBrowser: true,
14
+ });
15
+
16
+ const createGologinProfileManager = ({ profileId, ...params }) => {
15
17
  const defaults = getDefaultParams();
16
18
  const mergedParams = {
17
19
  ...defaults,
@@ -27,9 +29,7 @@ const createLegacyGologin = ({ profileId, ...params }) => {
27
29
 
28
30
  const createdApis = [];
29
31
 
30
- export const delay = (ms = 250) => new Promise((res) => setTimeout(res, ms));
31
-
32
- export function GologinApi({ token }) {
32
+ export const GologinApi = ({ token }) => {
33
33
  if (!token) {
34
34
  throw new Error('GoLogin API token is missing');
35
35
  }
@@ -38,7 +38,7 @@ export function GologinApi({ token }) {
38
38
  const legacyGls = [];
39
39
 
40
40
  const launchLocal = async (params) => {
41
- const legacyGologin = createLegacyGologin({
41
+ const legacyGologin = createGologinProfileManager({
42
42
  ...params,
43
43
  token,
44
44
  });
@@ -48,9 +48,9 @@ export function GologinApi({ token }) {
48
48
  await legacyGologin.setProfileId(id);
49
49
  }
50
50
 
51
- const started = await legacyGologin.start();
51
+ const startedProfile = await legacyGologin.start();
52
52
  const browser = await puppeteer.connect({
53
- browserWSEndpoint: started.wsUrl,
53
+ browserWSEndpoint: startedProfile.wsUrl,
54
54
  ignoreHTTPSErrors: true,
55
55
  });
56
56
 
@@ -61,7 +61,7 @@ export function GologinApi({ token }) {
61
61
  };
62
62
 
63
63
  const launchCloudProfile = async (params) => {
64
- const legacyGologin = createLegacyGologin({
64
+ const legacyGologin = createGologinProfileManager({
65
65
  ...params,
66
66
  token,
67
67
  });
@@ -94,7 +94,195 @@ export function GologinApi({ token }) {
94
94
  return launchLocal(params);
95
95
  },
96
96
 
97
- async exit(status = 0) {
97
+ async createProfileWithCustomParams(options) {
98
+ const response = await fetch(`${API_URL}/browser/custom`, {
99
+ method: 'POST',
100
+ headers: {
101
+ 'Authorization': `Bearer ${token}`,
102
+ 'User-Agent': 'gologin-api',
103
+ },
104
+ body: JSON.stringify(options),
105
+ });
106
+
107
+ if (response.status === 400) {
108
+ throw new Error(`gologin failed account creation with status code, ${response.status} DATA ${JSON.stringify(await response.json())}`);
109
+ }
110
+
111
+ if (response.status === 500) {
112
+ throw new Error(`gologin failed account creation with status code, ${response.status}`);
113
+ }
114
+
115
+ const profile = await response.json();
116
+
117
+ return profile.id;
118
+ },
119
+
120
+ async refreshProfilesFingerprint(profileIds) {
121
+ if (!profileIds) {
122
+ throw new Error('Profile ID is required');
123
+ }
124
+
125
+ const response = await fetch(`${API_URL}/browser/fingerprints`, {
126
+ headers: {
127
+ 'Authorization': `Bearer ${token}`,
128
+ 'User-Agent': 'gologin-api',
129
+ 'Content-Type': 'application/json',
130
+ },
131
+ method: 'PATCH',
132
+ body: JSON.stringify({ browsersIds: profileIds }),
133
+ });
134
+
135
+ return response.json();
136
+ },
137
+
138
+ async createProfileRandomFingerprint(name = '') {
139
+ const osInfo = await getOsAdvanced();
140
+ const { os, osSpec } = osInfo;
141
+ const resultName = name || 'api-generated';
142
+
143
+ const response = await fetch(`${API_URL}/browser/quick`, {
144
+ method: 'POST',
145
+ headers: {
146
+ 'Authorization': `Bearer ${token}`,
147
+ 'User-Agent': 'gologin-api',
148
+ 'Content-Type': 'application/json',
149
+ },
150
+ body: JSON.stringify({
151
+ os,
152
+ osSpec,
153
+ name: resultName,
154
+ }),
155
+ });
156
+
157
+ return response.json();
158
+ },
159
+
160
+ async updateUserAgentToLatestBrowser(profileIds, workspaceId = '') {
161
+ let url = `${API_URL}/browser/update_ua_to_new_browser_v`;
162
+ if (workspaceId) {
163
+ url += `?currentWorkspace=${workspaceId}`;
164
+ }
165
+
166
+ const response = await fetch(url, {
167
+ method: 'PATCH',
168
+ headers: {
169
+ 'Authorization': `Bearer ${token}`,
170
+ 'User-Agent': 'gologin-api',
171
+ 'Content-Type': 'application/json',
172
+ },
173
+ body: JSON.stringify({ browserIds: profileIds, updateUaToNewBrowserV: true, updateAllProfiles: false, testOrbita: false }),
174
+ });
175
+
176
+ return response.json();
177
+ },
178
+
179
+ async changeProfileProxy(profileId, proxyData) {
180
+ console.log(proxyData);
181
+ const response = await fetch(`${API_URL}/browser/${profileId}/proxy`, {
182
+ method: 'PATCH',
183
+ headers: {
184
+ Authorization: `Bearer ${token}`,
185
+ 'user-agent': 'gologin-api',
186
+ 'Content-Type': 'application/json',
187
+ },
188
+ body: JSON.stringify(proxyData),
189
+ });
190
+
191
+ return response.status;
192
+ },
193
+
194
+ getAvailableType(availableTrafficData) {
195
+ switch (true) {
196
+ case availableTrafficData.mobileTrafficData.trafficUsedBytes > availableTrafficData.mobileTrafficData.trafficLimitBytes:
197
+ return 'mobile';
198
+ case availableTrafficData.residentialTrafficData.trafficUsedBytes < availableTrafficData.residentialTrafficData.trafficLimitBytes:
199
+ return 'resident';
200
+ case availableTrafficData.dataCenterTrafficData.trafficUsedBytes < availableTrafficData.dataCenterTrafficData.trafficLimitBytes:
201
+ return 'dataCenter';
202
+ default:
203
+ return 'none';
204
+ }
205
+ },
206
+
207
+ async addGologinProxyToProfile(profileId, countryCode, proxyType = '') {
208
+ if (!proxyType) {
209
+ const availableTraffic = await fetch(`${API_URL}/users-proxies/geolocation/traffic`, {
210
+ headers: {
211
+ Authorization: `Bearer ${token}`,
212
+ 'user-agent': 'gologin-api',
213
+ 'Content-Type': 'application/json',
214
+ },
215
+ });
216
+
217
+ const availableTrafficData = await availableTraffic.json();
218
+ console.log(availableTrafficData);
219
+ const availableType = this.getAvailableType(availableTrafficData);
220
+ if (availableType === 'none') {
221
+ throw new Error(trafficLimitMessage);
222
+ }
223
+
224
+ console.log(availableType);
225
+ proxyType = availableType;
226
+ }
227
+
228
+ let isDc = false;
229
+ let isMobile = false;
230
+
231
+ switch (proxyType) {
232
+ case 'mobile':
233
+ isMobile = true;
234
+ isDc = false;
235
+ break;
236
+ case 'resident':
237
+ isMobile = false;
238
+ isDc = false;
239
+ break;
240
+ case 'dataCenter':
241
+ isMobile = false;
242
+ isDc = true;
243
+ break;
244
+ default:
245
+ throw new Error('Invalid proxy type');
246
+ }
247
+
248
+ const proxyResponse = await fetch(`${API_URL}/users-proxies/mobile-proxy`, {
249
+ headers: {
250
+ Authorization: `Bearer ${token}`,
251
+ 'user-agent': 'gologin-api',
252
+ 'Content-Type': 'application/json',
253
+ },
254
+ method: 'POST',
255
+ body: JSON.stringify({
256
+ countryCode,
257
+ isDc,
258
+ isMobile,
259
+ profileIdToLink: profileId,
260
+ }),
261
+ });
262
+
263
+ const proxy = await proxyResponse.json();
264
+ if (proxy.trafficLimitBytes < proxy.trafficUsedBytes) {
265
+ throw new Error(trafficLimitMessage);
266
+ }
267
+
268
+ return proxy;
269
+ },
270
+
271
+ async addCookiesToProfile(profileId, cookies) {
272
+ const response = await fetch(`${API_URL}/browser/${profileId}/cookies?fromUser=true`, {
273
+ method: 'POST',
274
+ headers: {
275
+ Authorization: `Bearer ${token}`,
276
+ 'user-agent': 'gologin-api',
277
+ 'Content-Type': 'application/json',
278
+ },
279
+ body: JSON.stringify(cookies),
280
+ });
281
+
282
+ return response.status;
283
+ },
284
+
285
+ async exit() {
98
286
  Promise.allSettled(browsers.map((browser) => browser.close()));
99
287
  Promise.allSettled(
100
288
  legacyGls.map((gl) => gl.stopLocal({ posting: false })),
@@ -103,14 +291,12 @@ export function GologinApi({ token }) {
103
291
  legacyGls.map((gl) => gl.stopRemote({ posting: true })),
104
292
  );
105
293
  },
106
-
107
- delay,
108
294
  };
109
295
 
110
296
  createdApis.push(api);
111
297
 
112
298
  return api;
113
- }
299
+ };
114
300
 
115
301
  export function exitAll() {
116
302
  Promise.allSettled(createdApis.map((api) => api.exit()));
package/src/gologin.js CHANGED
@@ -116,36 +116,6 @@ export class GoLogin {
116
116
  }
117
117
  }
118
118
 
119
- async getNewFingerPrint(os) {
120
- debug('GETTING FINGERPRINT');
121
-
122
- const fpResponse = await requests.get(`${API_URL}/browser/fingerprint?os=${os}`, {
123
- json: true,
124
- headers: {
125
- 'Authorization': `Bearer ${this.access_token}`,
126
- 'User-Agent': 'gologin-api',
127
- },
128
- });
129
-
130
- return fpResponse?.body || {};
131
- }
132
-
133
- async profiles() {
134
- const profilesResponse = await requests.get(`${API_URL}/browser/v2`, {
135
- headers: {
136
- 'Authorization': `Bearer ${this.access_token}`,
137
- 'User-Agent': 'gologin-api',
138
-
139
- },
140
- });
141
-
142
- if (profilesResponse.statusCode !== 200) {
143
- throw new Error('Gologin /browser response error');
144
- }
145
-
146
- return JSON.parse(profilesResponse.body);
147
- }
148
-
149
119
  async getProfile(profile_id) {
150
120
  const id = profile_id || this.profile_id;
151
121
  debug('getProfile', this.access_token, id);
@@ -509,6 +479,7 @@ export class GoLogin {
509
479
  const prefFileExists = await access(pref_file_name).then(() => true).catch(() => false);
510
480
  if (!prefFileExists) {
511
481
  debug('Preferences file not exists waiting', pref_file_name, '. Using empty profile');
482
+ await mkdir(join(profilePath, 'Default'), { recursive: true });
512
483
  await writeFile(pref_file_name, '{}');
513
484
  }
514
485
 
@@ -1234,48 +1205,6 @@ export class GoLogin {
1234
1205
  return response.body.id;
1235
1206
  }
1236
1207
 
1237
- async createCustom(options) {
1238
- debug('createCustomProfile', options);
1239
- const response = await requests.post(`${API_URL}/browser/custom`, {
1240
- headers: {
1241
- 'Authorization': `Bearer ${this.access_token}`,
1242
- 'User-Agent': 'gologin-api',
1243
- },
1244
- json: options,
1245
- });
1246
-
1247
- if (response.statusCode === 400) {
1248
- throw new Error(`gologin failed account creation with status code, ${response.statusCode} DATA ${JSON.stringify(response.body.message)}`);
1249
- }
1250
-
1251
- if (response.statusCode === 500) {
1252
- throw new Error(`gologin failed account creation with status code, ${response.statusCode}`);
1253
- }
1254
-
1255
- debug(JSON.stringify(response));
1256
-
1257
- return response.body.id;
1258
- }
1259
-
1260
- async quickCreateProfile(name = '') {
1261
- const osInfo = await getOsAdvanced();
1262
- const { os, osSpec } = osInfo;
1263
- const resultName = name || 'api-generated';
1264
-
1265
- return requests.post(`${API_URL}/browser/quick`, {
1266
- headers: {
1267
- 'Authorization': `Bearer ${this.access_token}`,
1268
- 'User-Agent': 'gologin-api',
1269
- },
1270
- json: {
1271
- os,
1272
- osSpec,
1273
- name: resultName,
1274
- },
1275
- })
1276
- .then(res => res.body);
1277
- }
1278
-
1279
1208
  async delete(pid) {
1280
1209
  const profile_id = pid || this.profile_id;
1281
1210
  await requests.delete(`${API_URL}/browser/${profile_id}`, {
@@ -1451,7 +1380,6 @@ export class GoLogin {
1451
1380
  }
1452
1381
 
1453
1382
  async start() {
1454
-
1455
1383
  await this.createStartup();
1456
1384
  // await this.createBrowserExtension();
1457
1385
  const wsUrl = await this.spawnBrowser();
@@ -1524,22 +1452,72 @@ export class GoLogin {
1524
1452
  }
1525
1453
  }
1526
1454
 
1455
+ // api for users to manage their profiles
1456
+ async changeProfileProxy(proxyData) {
1457
+ return updateProfileProxy(this.profile_id, this.access_token, proxyData);
1458
+ }
1459
+
1460
+ async changeProfileUserAgent(userAgent) {
1461
+ return updateProfileUserAgent(this.profile_id, this.access_token, userAgent);
1462
+ }
1463
+
1464
+ async changeProfileResolution(resolution) {
1465
+ return updateProfileResolution(this.profile_id, this.access_token, resolution);
1466
+ }
1467
+
1527
1468
  getAvailableFonts() {
1528
1469
  return fontsCollection
1529
1470
  .filter(elem => elem.fileNames)
1530
1471
  .map(elem => elem.name);
1531
1472
  }
1532
1473
 
1533
- async changeProfileResolution(resolution) {
1534
- return updateProfileResolution(this.profile_id, this.access_token, resolution);
1474
+ async quickCreateProfile(name = '') {
1475
+ const osInfo = await getOsAdvanced();
1476
+ const { os, osSpec } = osInfo;
1477
+ const resultName = name || 'api-generated';
1478
+
1479
+ return requests.post(`${API_URL}/browser/quick`, {
1480
+ headers: {
1481
+ 'Authorization': `Bearer ${this.access_token}`,
1482
+ 'User-Agent': 'gologin-api',
1483
+ },
1484
+ json: {
1485
+ os,
1486
+ osSpec,
1487
+ name: resultName,
1488
+ },
1489
+ })
1490
+ .then(res => res.body);
1535
1491
  }
1536
1492
 
1537
- async changeProfileUserAgent(userAgent) {
1538
- return updateProfileUserAgent(this.profile_id, this.access_token, userAgent);
1493
+ async profiles() {
1494
+ const profilesResponse = await requests.get(`${API_URL}/browser/v2`, {
1495
+ headers: {
1496
+ 'Authorization': `Bearer ${this.access_token}`,
1497
+ 'User-Agent': 'gologin-api',
1498
+
1499
+ },
1500
+ });
1501
+
1502
+ if (profilesResponse.statusCode !== 200) {
1503
+ throw new Error('Gologin /browser response error');
1504
+ }
1505
+
1506
+ return JSON.parse(profilesResponse.body);
1539
1507
  }
1540
1508
 
1541
- async changeProfileProxy(proxyData) {
1542
- return updateProfileProxy(this.profile_id, this.access_token, proxyData);
1509
+ async getNewFingerPrint(os) {
1510
+ debug('GETTING FINGERPRINT');
1511
+
1512
+ const fpResponse = await requests.get(`${API_URL}/browser/fingerprint?os=${os}`, {
1513
+ json: true,
1514
+ headers: {
1515
+ 'Authorization': `Bearer ${this.access_token}`,
1516
+ 'User-Agent': 'gologin-api',
1517
+ },
1518
+ });
1519
+
1520
+ return fpResponse?.body || {};
1543
1521
  }
1544
1522
  }
1545
1523
 
@@ -47,3 +47,4 @@ export const findLatestBrowserVersionDirectory = (browserPath) => {
47
47
  return folderName;
48
48
  };
49
49
 
50
+ export const delay = (ms = 250) => new Promise((res) => setTimeout(res, ms));
@@ -0,0 +1,127 @@
1
+ export type OS = 'lin' | 'mac' | 'win' | 'android';
2
+ export type T_OS_SPEC = 'M1' | 'M2' | 'M3' | 'M3' | 'win11' | '';
3
+
4
+ export type IBookmarkFoldersObj = {
5
+ [key: string]: {
6
+ name: string;
7
+ children: Array<{
8
+ name: string;
9
+ url: string;
10
+ }>;
11
+ };
12
+ }
13
+
14
+ export type NavigatorModel = {
15
+ userAgent: string;
16
+ resolution: string;
17
+ language: string;
18
+ platform: string;
19
+ hardwareConcurrency: number;
20
+ deviceMemory: number;
21
+ maxTouchPoints?: number;
22
+ }
23
+
24
+ export type TimezoneModel = {
25
+ enabled: boolean;
26
+ fillBasedOnIp: boolean;
27
+ timezone: string;
28
+ }
29
+
30
+ export type GeolocationModel = {
31
+ mode: 'prompt' | 'block' | 'allow';
32
+ enabled: boolean;
33
+ customize: boolean;
34
+ fillBasedOnIp: boolean;
35
+ latitude: number;
36
+ longitude: number;
37
+ accuracy: number;
38
+ }
39
+
40
+ export type AudioContextModel = {
41
+ enable: boolean;
42
+ noiseValue: number;
43
+ }
44
+
45
+ export type CanvasModel = {
46
+ mode: 'off' | 'noise';
47
+ noise?: number;
48
+ }
49
+
50
+ export type FontsModel = {
51
+ enableMasking: boolean;
52
+ enableDOMRect: boolean;
53
+ families: string[];
54
+ }
55
+
56
+ export type MediaDevicesModel = {
57
+ enableMasking: boolean;
58
+ videoInputs: number;
59
+ audioInputs: number;
60
+ audioOutputs: number;
61
+ }
62
+
63
+ export type WebRTCModel = {
64
+ mode: 'real' | 'public';
65
+ enabled: boolean;
66
+ customize: boolean;
67
+ localIpMasking: boolean;
68
+ fillBasedOnIp: boolean;
69
+ publicIp: string;
70
+ localIps: string[];
71
+ }
72
+
73
+ export type WebGlModel = {
74
+ mode: 'off' | 'noise';
75
+ getClientRectsNoise: number;
76
+ noise?: number;
77
+ }
78
+
79
+ export type ClientRectsModel = {
80
+ mode: 'off' | 'noise';
81
+ noise: number;
82
+ }
83
+
84
+ export type WebGlMetadataModel {
85
+ mode: 'off' | 'mask';
86
+ vendor: string;
87
+ renderer: string;
88
+ }
89
+
90
+ export type BrowserProxyCreateValidation {
91
+ mode: 'http' | 'https' | 'socks4' | 'socks5' | 'geolocation' | 'none' | 'tor' | 'gologin';
92
+ host: string;
93
+ port: number;
94
+ username?: string;
95
+ password?: string;
96
+ changeIpUrl?: string;
97
+ autoProxyRegion?: string;
98
+ torProxyRegion?: string;
99
+ }
100
+
101
+ export declare class CreateCustomBrowserValidation {
102
+ name?: string;
103
+ notes?: string;
104
+ autoLang?: boolean;
105
+ lockEnabled?: boolean;
106
+ folderName?: string;
107
+ bookmarks?: IBookmarkFoldersObj;
108
+ os: OS;
109
+ osSpec?: T_OS_SPEC;
110
+ devicePixelRatio?: number;
111
+ navigator?: NavigatorModel;
112
+ proxy?: BrowserProxyCreateValidation;
113
+ dns?: string;
114
+ timezone?: TimezoneModel;
115
+ geolocation?: GeolocationModel;
116
+ audioContext?: AudioContextModel;
117
+ canvas?: CanvasModel;
118
+ fonts?: FontsModel;
119
+ mediaDevices?: MediaDevicesModel;
120
+ webRTC?: WebRTCModel;
121
+ webGL?: WebGlModel;
122
+ clientRects?: ClientRectsModel;
123
+ webGLMetadata?: WebGlMetadataModel;
124
+ chromeExtensions?: string[];
125
+ userChromeExtensions?: string[];
126
+ folders?: string[];
127
+ }