KitsuLabs
.
Edit Snippet
Perbarui kode atau detail snippet ini.
Filename / Title
Language
JavaScript
Python
HTML
CSS
JSON
SQL
Bash
TypeScript
PHP
Java
Go
Rust
Description
(Optional)
Access chatgpt without login, support continuing chat, streaming, web search, and uploading images.
Tags
Code Content
*
/*** @ Base: https://chatgpt.com/ @ Author: Shannz @ Note: Access chatgpt without login, support continuing chat, streaming, web search, and uploading images. ***/ import crypto from "crypto"; import fs from "fs"; import path from "path"; let _fetch = globalThis.fetch; if (!_fetch) { const { fetch } = await import("undici"); _fetch = fetch; } let _perf = globalThis.performance; if (!_perf) { const { performance } = await import("perf_hooks"); _perf = performance; } export class ChatGPT { constructor(cfg = {}) { this.baseUrl = "https://chatgpt.com"; this.userAgent = cfg.userAgent ?? "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Mobile Safari/537.36"; this.oaiDid = cfg.did ?? crypto.randomUUID(); this.screenWidth = cfg.screenWidth ?? 423; this.screenHeight = cfg.screenHeight ?? 965; this.lang = cfg.lang ?? "id-ID"; this.buildNumber = cfg.buildNumber ?? "prod-69a06c53754594935887d6c16b844885964a78fc"; this.authToken = cfg.authToken ?? null; } async send(message, opts = {}) { if (!message?.trim()) throw new Error("Pesan tidak boleh kosong."); const { conversationId = null, parentMessageId = null, imagePath = null, webSearch = false, stream = false, onChunk, } = opts; const parentMsgId = parentMessageId ?? "client-created-root"; const msgId = crypto.randomUUID(); let image = null; if (imagePath) { image = await this._uploadImage(imagePath, { conversationId, parentMsgId }); } const [tokens, conduitToken] = await Promise.all([ this._generateSentinelTokens(), this._getConduitToken(message, msgId, { conversationId, parentMsgId, webSearch, image }), ]); const body = this._buildMessageBody(message, msgId, { conversationId, parentMsgId, webSearch, image, }); const res = await _fetch(`${this.baseUrl}/backend-anon/f/conversation`, { method: "POST", body: JSON.stringify(body), headers: this._headers({ "accept": "text/event-stream", "OAI-Language": this.lang, "OpenAI-Sentinel-Chat-Requirements-Token": tokens.chatRequirementsToken, "OpenAI-Sentinel-Turnstile-Token": tokens.turnstile, "OpenAI-Sentinel-Proof-Token": tokens.pow, "X-Conduit-Token": conduitToken, }), }); if (!res.ok) { const err = await res.text().catch(() => "(no body)"); throw new Error(`HTTP ${res.status}: ${err}`); } return this._parseSSE(res.body, { stream, onChunk }); } async _uploadImage(filePath, ctx = {}) { const fileBuffer = fs.readFileSync(filePath); const fileName = path.basename(filePath); const mimeType = this._getMimeType(fileName); const sizeBytes = fileBuffer.length; const { width, height } = this._getImageDimensions(fileBuffer, mimeType); const registerRes = await _fetch(`${this.baseUrl}/backend-anon/files`, { method: "POST", headers: this._headers(), body: JSON.stringify({ file_name: fileName, file_size: sizeBytes, use_case: "multimodal", timezone_offset_min: new Date().getTimezoneOffset(), reset_rate_limits: false, }), }).then(r => r.json()); const { upload_url, file_id } = registerRes; if (!upload_url || !file_id) { throw new Error(`Gagal mendaftar file: ${JSON.stringify(registerRes)}`); } const uploadRes = await _fetch(upload_url, { method: "PUT", headers: { "Content-Type": mimeType, "x-ms-blob-type": "BlockBlob", "x-ms-version": "2020-04-08", }, body: fileBuffer, }); if (!uploadRes.ok) { throw new Error(`Upload blob gagal: HTTP ${uploadRes.status}`); } const processBody = { file_id, use_case: "multimodal", index_for_retrieval: false, file_name: fileName, }; if (ctx.conversationId || ctx.parentMsgId) { processBody.metadata = { library_file_info: { origination_message_id: ctx.parentMsgId ?? null, origination_thread_id: ctx.conversationId ?? null, }, }; } const processRes = await _fetch( `${this.baseUrl}/backend-anon/files/process_upload_stream`, { method: "POST", headers: this._headers(), body: JSON.stringify(processBody) } ); const decoder = new TextDecoder(); let buf = ""; for await (const chunk of processRes.body) { buf += decoder.decode(chunk, { stream: true }); if (buf.includes("file.processing.completed")) break; } return { fileId: file_id, fileName, mimeType, sizeBytes, width, height }; } _headers(extra = {}) { return { "User-Agent": this.userAgent, "accept": "*/*", "accept-language": `${this.lang},en-US;q=0.9,en;q=0.8`, "content-type": "application/json", "OAI-Device-Id": this.oaiDid, "sec-ch-ua": '"Chromium";v="144", "Not/A)Brand";v="24"', "sec-ch-ua-mobile": "?1", "sec-ch-ua-platform": '"Android"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", "origin": "https://chatgpt.com", "referer": "https://chatgpt.com/", ...(this.authToken ? { "authorization": `Bearer ${this.authToken}` } : {}), ...extra, }; } _fnv1a(str) { let h = 2166136261; for (let i = 0; i < str.length; i++) { h ^= str.charCodeAt(i); h = Math.imul(h, 16777619) >>> 0; } h ^= h >>> 16; h = Math.imul(h, 2246822507) >>> 0; h ^= h >>> 13; h = Math.imul(h, 3266489909) >>> 0; h ^= h >>> 16; return (h >>> 0).toString(16).padStart(8, "0"); } _encodeConfig(cfg) { return Buffer.from(JSON.stringify(cfg)).toString("base64"); } _makeBrowserConfig() { return [ this.screenWidth + this.screenHeight, String(new Date()), 2172649472, 0, this.userAgent, null, this.buildNumber, this.lang, `${this.lang},en`, 0, "contacts\u2212[object ContactsManager]", "_reactListening", "User", _perf.now(), crypto.randomUUID(), "", 8, _perf.timeOrigin, 0, 0, 0, 0, 0, 0, 0, ]; } _computePow(seed, difficulty, cfg) { const start = _perf.now(); for (let i = 0; i < 500_000; i++) { cfg[3] = i; cfg[9] = Math.round(_perf.now() - start); const encoded = this._encodeConfig(cfg); if (this._fnv1a(seed + encoded).substring(0, difficulty.length) <= difficulty) { return "gAAAAAB" + encoded + "~S"; } } return "wQ8Lk5FbGpA2NcR9dShT6gYjU7VxZ4De"; } async _generateSentinelTokens() { const initCfg = this._makeBrowserConfig(); initCfg[3] = 1; initCfg[9] = 0; const initToken = "gAAAAAC" + this._encodeConfig(initCfg); const prepareRes = await _fetch( `${this.baseUrl}/backend-anon/sentinel/chat-requirements/prepare`, { method: "POST", headers: this._headers(), body: JSON.stringify({ p: initToken }) } ).then(r => r.json()); let pow = null; if (prepareRes.proofofwork?.required) { pow = this._computePow( prepareRes.proofofwork.seed, prepareRes.proofofwork.difficulty, this._makeBrowserConfig() ); } const turnstile = crypto .randomBytes(Math.floor((2256 / 4) * 3)) .toString("base64") .slice(0, 2256); const finalizeBody = { prepare_token: prepareRes.prepare_token ?? "" }; if (pow) finalizeBody.proofofwork = pow; if (turnstile) finalizeBody.turnstile = turnstile; const finalizeRes = await _fetch( `${this.baseUrl}/backend-anon/sentinel/chat-requirements/finalize`, { method: "POST", headers: this._headers(), body: JSON.stringify(finalizeBody) } ).then(r => r.json()); return { pow, turnstile, chatRequirementsToken: finalizeRes.token ?? null }; } async _getConduitToken(message, msgId, { conversationId, parentMsgId, webSearch, image }) { const body = { action: "next", fork_from_shared_post: false, parent_message_id: parentMsgId, model: "auto", timezone_offset_min: new Date().getTimezoneOffset(), timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, conversation_mode: { kind: "primary_assistant" }, system_hints: webSearch ? ["search"] : [], supports_buffering: true, supported_encodings: ["v1"], partial_query: { id: msgId, author: { role: "user" }, content: { content_type: "text", parts: [message] }, }, client_contextual_info: { app_name: "chatgpt.com" }, }; if (conversationId) body.conversation_id = conversationId; if (image) body.attachment_mime_types = [image.mimeType]; const res = await _fetch( `${this.baseUrl}/backend-anon/f/conversation/prepare`, { method: "POST", headers: this._headers({ "X-Conduit-Token": "no-token" }), body: JSON.stringify(body), } ); const data = await res.json(); return data.token ?? data.conduit_token; } _buildMessageBody(message, msgId, { conversationId, parentMsgId, webSearch, image }) { let content, msgMeta; if (image) { content = { content_type: "multimodal_text", parts: [ { content_type: "image_asset_pointer", asset_pointer: `file-service://${image.fileId}`, size_bytes: image.sizeBytes, width: image.width, height: image.height, }, message, ], }; msgMeta = { attachments: [{ id: image.fileId, size: image.sizeBytes, name: image.fileName, mime_type: image.mimeType, width: image.width, height: image.height, source: "local", is_big_paste: false, }], selected_github_repos: [], selected_all_github_repos: false, serialization_metadata: { custom_symbol_offsets: [] }, }; } else { content = { content_type: "text", parts: [message] }; msgMeta = { selected_github_repos: [], selected_all_github_repos: false, serialization_metadata: { custom_symbol_offsets: [] }, ...(webSearch ? { system_hints: ["search"] } : {}), }; } const body = { action: "next", messages: [{ id: msgId, author: { role: "user" }, create_time: Date.now() / 1000, content, metadata: msgMeta, }], parent_message_id: parentMsgId, model: "auto", timezone_offset_min: new Date().getTimezoneOffset(), timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, conversation_mode: { kind: "primary_assistant" }, enable_message_followups: true, system_hints: webSearch ? ["search"] : [], supports_buffering: true, supported_encodings: ["v1"], client_contextual_info: { is_dark_mode: true, time_since_loaded: 10, page_height: 845, page_width: 423, pixel_ratio: 1.7, screen_height: this.screenHeight, screen_width: this.screenWidth, app_name: "chatgpt.com", }, no_auth_ad_preferences: { personalization_enabled: true, history_enabled: true, }, paragen_cot_summary_display_override: "allow", force_parallel_switch: "auto", }; if (conversationId) body.conversation_id = conversationId; if (webSearch) { body.force_use_search = true; body.client_reported_search_source = "conversation_composer_web_icon"; } return body; } async _parseSSE(body, { stream, onChunk }) { const decoder = new TextDecoder(); let buf = ""; let fullText = ""; let title = null; let model = null; let convId = null; let assistantMsgId = null; for await (const chunk of body) { buf += decoder.decode(chunk, { stream: true }); const lines = buf.split("\n"); buf = lines.pop() ?? ""; for (const line of lines) { if (!line.startsWith("data:")) continue; const raw = line.slice(5).trim(); if (!raw || raw === "[DONE]") continue; let json; try { json = JSON.parse(raw); } catch { continue; } if (json.conversation_id) { convId = json.conversation_id; } else if (json.v?.conversation_id) { convId = json.v.conversation_id; } if ( json.v && !Array.isArray(json.v) && json.v.message?.author?.role === "assistant" && json.v.message?.id ) { assistantMsgId = json.v.message.id; } if (json.type === "title_generation") title = json.title; if (json.type === "server_ste_metadata") model = json.metadata?.model_slug ?? null; const patches = Array.isArray(json.v) ? json.v : []; for (const p of patches) { if (p.o === "append" && p.p?.includes("/message/content/parts/0")) { fullText += p.v; if (stream && typeof onChunk === "function") onChunk(p.v); } } } } return { text: fullText, title, model, conversationId: convId, messageId: assistantMsgId, }; } _getMimeType(fileName) { const ext = path.extname(fileName).toLowerCase(); return { ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".gif": "image/gif", ".webp": "image/webp", }[ext] ?? "application/octet-stream"; } _getImageDimensions(buffer, mimeType) { try { if (mimeType === "image/png") { return { width: buffer.readUInt32BE(16), height: buffer.readUInt32BE(20) }; } if (mimeType === "image/jpeg") { let i = 2; while (i < buffer.length - 8) { if (buffer[i] !== 0xFF) break; const marker = buffer[i + 1]; const segLen = buffer.readUInt16BE(i + 2); if (marker >= 0xC0 && marker <= 0xC3) { return { height: buffer.readUInt16BE(i + 5), width: buffer.readUInt16BE(i + 7) }; } i += 2 + segLen; } } } catch { } return { width: 0, height: 0 }; } } /* const chat = new ChatGPT({ lang: "id-ID" }); // New Chat console.log("── Turn 1: Chat baru ──"); const r1 = await chat.send("Halo, namaku Shannz."); console.log("Bot:", r1.text); console.log("Model:", r1.model); console.log("ConvID:", r1.conversationId); console.log("MessageID:", r1.messageId); // Continue Chat console.log("\n── Turn 2: Lanjut chat ──"); const r2 = await chat.send("Siapa namaku tadi?", { conversationId: r1.conversationId, parentMessageId: r1.messageId, }); console.log("Bot:", r2.text); // New Chat with pictures console.log("\n── Turn 3: Kirim gambar ──"); const r3 = await chat.send("Gambar apa ini?", { imagePath: "./screenshot.png", }); console.log("Bot:", r3.text); console.log("ConvID:", r3.conversationId, "| MsgID:", r3.messageId); // Continue Chat with pictures console.log("\n── Turn 4: Lanjut chat gambar ──"); const r4 = await chat.send("Ceritakan lebih detail!", { conversationId: r3.conversationId, parentMessageId: r3.messageId, }); console.log("Bot:", r4.text); // Stream & Web Search Mode process.stdout.write("\n── Turn 5: Streaming Mode ──\nBot: "); await chat.send("Sebutkan 3 bahasa pemrograman!", { conversationId: r2.conversationId, parentMessageId: r2.messageId, webSearch: true, stream: true, onChunk: (t) => process.stdout.write(t), }); console.log(); */
Editor is always dark mode for better readability.
Admin Access
Update Snippet
Cancel