· last year · Feb 25, 2024, 03:00 AM
1// Script demonstrates automatic sign in to your Roblox account
2// Replace API key, login, password and proxy credentials with your own.
3//
4// Install packages:
5// npm install @antiadmin/anticaptchaofficial puppeteer
6//
7// run with command: "node roblox.js"
8
9
10const ac = require("@antiadmin/anticaptchaofficial");
11const pup = require("puppeteer");
12
13
14ac.setAPIKey('API_KEY_HERE');
15ac.getBalance()
16 .then(balance => console.log('my balance is: '+balance))
17 .catch(error => console.log('an error with API key: '+error));
18
19
20const login = 'YOUR_LOGIN';
21const password = 'YOUR_PASSWORD';
22
23const proxyAddress = "11.22.33.44"; //only numbers
24const proxyPort = "1234"
25const proxyUser = "mylogin";
26const proxyPassword = 'mypassword';
27
28//use unique browser agent
29let userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36';
30let browser = null;
31let tab = null;
32
33(async () => {
34try {
35
36 let xfrToken = null;
37 let dataBlob = null;
38
39 await prepareBrowser();
40
41 console.log('setting response hook ..');
42 //response interception to catch XHR token
43 const xfrCatchPromise = new Promise((resolve, reject) => {
44 tab.on('response', async (response) => {
45 if (response.url() === "https://auth.roblox.com/v2/login" && xfrToken == null){
46 console.log('XHR response received');
47 let result = await response;
48 let json = await result.json();
49
50 if (json === null) {
51 reject('JSON is null');
52 return false;
53 }
54
55 console.log('intercepted response JSON:')
56 console.log(json);
57 const dataBlob = json.errors[0]["fieldData"];
58 console.log('data blob: '+dataBlob);
59
60 xfrToken = result._request._headers['x-csrf-token'];
61 console.log('xfr token: '+xfrToken);
62 resolve({xfrToken, dataBlob })
63 }
64 });
65 });
66
67
68 console.log('opening target page ..');
69 //not using waitUntil:"networkidle0" option, sometimes causes page to never load
70 await tab.goto('https://www.roblox.com/newlogin', {waitUntil: "domcontentloaded"});
71
72 //let everything load
73 console.log('waiting 5 seconds');
74 await delay(5000);
75
76 //use this to skip "accept all cookies" button
77 await tab.click("#login-username");
78 await delay(1000);
79
80 console.log('filling login ..');
81 await tab.click("#login-username");
82 await tab.keyboard.type(login,{delay: 100});
83
84 console.log('filling password ..');
85 await tab.click("#login-password");
86 await tab.keyboard.type(password,{delay: 100});
87
88 await delay(5000);
89 console.log('submitting form ..');
90
91 [_, { xfrToken, dataBlob } ] = await Promise.all([
92 tab.click("#login-button"),
93 xfrCatchPromise,
94 ]);
95
96 const dataBlobObject = JSON.parse(dataBlob);
97
98 if (typeof dataBlobObject.unifiedCaptchaId === "undefined" || xfrToken === null) {
99 throw new Error("something went wrong");
100 }
101
102 const token = await solveArkoselabsCaptcha(dataBlobObject.dxBlob);
103 console.log('Funcaptcha token from Anti-Captcha: '+token);
104
105 const user = await makeAJAXRequestWithXFR(xfrToken, dataBlobObject.unifiedCaptchaId, token);
106 if (user.user.name === login) console.log('completed successfully');
107 else console.log('wrong user name');
108
109
110} catch (e) {
111 console.error('could not complete requests: '+e.toString())
112}
113
114browser.close();
115
116})();
117
118
119
120function delay(time) {
121 return new Promise(function(resolve) {
122 setTimeout(resolve, time)
123 });
124}
125
126async function prepareBrowser() {
127 try {
128 console.log('opening browser ..');
129 let options = {
130 headless: true, //set to false if you want to see what's going on with the browser
131 ignoreHTTPSErrors: true,
132 devtools: false, //enable for debugging
133 ignoreDefaultArgs: ["--disable-extensions","--enable-automation"],
134 args: [
135 '--disable-web-security',
136 '--disable-features=IsolateOrigins,site-per-process',
137 '--allow-running-insecure-content',
138 '--disable-blink-features=AutomationControlled',
139 '--no-sandbox',
140 '--mute-audio',
141 '--no-zygote',
142 '--no-xshm',
143 '--window-size=1920,1080',
144 '--no-first-run',
145 '--no-default-browser-check',
146 '--disable-dev-shm-usage',
147 '--disable-gpu',
148 '--enable-webgl',
149 '--ignore-certificate-errors',
150 '--lang=en-US,en;q=0.9',
151 '--password-store=basic',
152 '--disable-gpu-sandbox',
153 '--disable-software-rasterizer',
154 '--disable-background-timer-throttling',
155 '--disable-backgrounding-occluded-windows',
156 '--disable-renderer-backgrounding',
157 '--disable-infobars',
158 '--disable-breakpad',
159 '--disable-canvas-aa',
160 '--disable-2d-canvas-clip-aa',
161 '--disable-gl-drawing-for-tests',
162 '--enable-low-end-device-mode'
163 ]
164 };
165 if (proxyAddress && proxyPort) {
166 options["args"].push(`--proxy-server=${proxyAddress}:${proxyPort}`);
167 }
168 browser = await pup.launch(options);
169
170 console.log('creating new tab ..');
171 tab = await browser.newPage();
172 } catch (e) {
173 console.log(e);
174 return false;
175 }
176
177
178 if (proxyPassword && proxyUser) {
179 console.log(`setting proxy authentication ${proxyPassword}:${proxyUser}`);
180 await tab.authenticate({
181 username: proxyUser,
182 password: proxyPassword,
183 });
184 }
185
186 await tab.setUserAgent(userAgent);
187 await tab.setViewport({width: 1920, height: 1080});
188
189 await tab.setRequestInterception(true);
190
191 tab.on('request', request => {
192
193 // preventing single-use dataBlob to be spent
194 if (request.url().indexOf('public_key/476068BF-9607-4799-B53D-966BE98E2B81') !== -1) {
195 console.log('Aborting URL request:' + request.url());
196 request.abort();
197 } else {
198 request.continue();
199 }
200 });
201
202 return true;
203
204}
205
206async function solveArkoselabsCaptcha(dataBlob) {
207
208 ac.settings.funcaptchaApiJSSubdomain = 'roblox-api.arkoselabs.com';
209 ac.settings.funcaptchaDataBlob = dataBlob;
210 try {
211
212
213 return await ac.solveFunCaptchaProxyOn(
214 'https://www.roblox.com/login',
215 '476068BF-9607-4799-B53D-966BE98E2B81',
216 'http',
217 proxyAddress,
218 proxyPort,
219 proxyUser,
220 proxyPassword,
221 userAgent);
222
223
224 } catch (e) {
225 throw new Error('Captcha not solved');
226 }
227}
228
229async function makeAJAXRequestWithXFR(xfrToken, captchaId, token) {
230
231 const evalParams = {
232 captchaId,
233 login,
234 password,
235 xfrToken,
236 token
237 };
238
239 //access to console log
240 tab.on('console', msg => console.log('PAGE LOG:', msg.text()));
241
242 const userJSON =
243 await tab.evaluate(async (evalParams) => {
244 return new Promise((resolve, reject) => {
245
246 console.log('making ajax call with login ' + evalParams.login + ', password ' + evalParams.password + ', XFR token "' + evalParams.xfrToken + '" and funcaptcha token "' + evalParams.token + '"');
247 fetch('https://auth.roblox.com/v2/login', {
248 method: "POST",
249 body: JSON.stringify({
250 "captchaId": evalParams.captchaId,
251 "cvalue": evalParams.login,
252 "ctype": "Username",
253 "password": evalParams.password,
254 "captchaToken": evalParams.token
255 }),
256 headers: {
257 'Content-Type': 'application/json;charset=UTF-8',
258 'Accept': 'application/json, text/plain, */*',
259 'x-csrf-token': evalParams.xfrToken
260 }
261 }).then(response => response.json())
262 .then(resultJSON => {
263
264
265 console.log('JSON result:')
266 console.log(resultJSON);
267
268 if (resultJSON.errors) {
269 if (resultJSON.errors[0]["code"] === 2) {
270 console.log('did not pass captcha');
271 reject('did not pass captcha');
272 return false;
273 }
274 if (resultJSON.errors[0]["code"] === 0) {
275 console.log('Token Validation Failed');
276 reject('Token Validation Failed');
277 return false;
278 }
279 console.log('unknown error: ' + resultJSON.errors[0]["message"]);
280 reject(resultJSON.errors[0]["message"]);
281 return false;
282 }
283 if (resultJSON.user) {
284 console.log('captcha accepted, user object is included in response');
285 resolve(resultJSON);
286 return true;
287 } else {
288 resolve('user object not found');
289 return false;
290 }
291
292 }).catch(err => {
293 console.log('catched AJAX error: ' + err.toString());
294 reject('catched AJAX error: ' + err.toString())
295 });
296
297
298 });
299
300
301 }, evalParams);
302
303 console.log('completed successfully');
304 console.log(userJSON);
305 return userJSON;
306
307
308}
309