{"id":13434526,"url":"https://github.com/terminalcommandnewsletter/everything-chatgpt","last_synced_at":"2025-03-17T14:31:34.460Z","repository":{"id":142412937,"uuid":"611831701","full_name":"terminalcommandnewsletter/everything-chatgpt","owner":"terminalcommandnewsletter","description":"🔍 Explore what happens under the hood with the ChatGPT web app, its backend API calls and more. And some speculation, of course.","archived":false,"fork":false,"pushed_at":"2023-08-16T08:15:34.000Z","size":1714,"stargazers_count":579,"open_issues_count":2,"forks_count":29,"subscribers_count":12,"default_branch":"main","last_synced_at":"2024-10-27T14:45:46.143Z","etag":null,"topics":["api","backend","chatgpt","webapp"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc-by-sa-4.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/terminalcommandnewsletter.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-03-09T16:26:26.000Z","updated_at":"2024-10-24T07:33:33.000Z","dependencies_parsed_at":"2024-01-14T10:00:14.560Z","dependency_job_id":"5ab5d0bb-fb58-483d-9fbb-240f8758b953","html_url":"https://github.com/terminalcommandnewsletter/everything-chatgpt","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terminalcommandnewsletter%2Feverything-chatgpt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terminalcommandnewsletter%2Feverything-chatgpt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terminalcommandnewsletter%2Feverything-chatgpt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terminalcommandnewsletter%2Feverything-chatgpt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/terminalcommandnewsletter","download_url":"https://codeload.github.com/terminalcommandnewsletter/everything-chatgpt/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244050277,"owners_count":20389666,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","backend","chatgpt","webapp"],"created_at":"2024-07-31T02:01:59.816Z","updated_at":"2025-03-17T14:31:33.758Z","avatar_url":"https://github.com/terminalcommandnewsletter.png","language":null,"funding_links":[],"categories":["Openai","Other","Others"],"sub_categories":["Other sdk/libraries"],"readme":"\u003cdiv align=\"center\"\u003e\n\n  # Everything ChatGPT\n  \u003ci\u003eA project by [@tercmd (on Twitter)](https://twitter.com/tercmd)\u003c/i\u003e\n\n  ![Stars for the Everything ChatGPT repo](https://img.shields.io/github/stars/terminalcommandnewsletter/everything-chatgpt?style=for-the-badge\u0026logo=github)\n\n  Explore what happens under the hood with the ChatGPT web app. And some speculation, of course. [Contribute if you have something interesting related to ChatGPT.](./CONTRIBUTING.md)\n\n\u003c/div\u003e\n\nThe repo no longer contains a Table of Contents because GitHub already shows this.\n\n## Fonts _([fonts.txt](./fonts.txt))_\n\u003e **Warning**\n\u003e **All fonts in the previous list are no longer accessible at the `https://chat.openai.com/fonts/[font]` endpoint. The new fonts.txt file assumes the prefix of the URLs to be `https://cdn.openai.com/common/fonts/`**\n\n**This is a _non exhaustive_ list of fonts that come from cdn.openai.com:**\n- [soehne-buch.woff2](https://cdn.openai.com/common/fonts/soehne/soehne-buch.woff2)\n- [soehne-halbfett.woff2](https://cdn.openai.com/common/fonts/soehne/soehne-halbfett.woff2)\n- [soehne-mono-buch.woff2](https://cdn.openai.com/common/fonts/soehne/soehne-mono-buch.woff2)\n- [soehne-mono-halbfett.woff2](https://cdn.openai.com/common/fonts/soehne/soehne-mono-halbfett.woff2)\n- [soehne-kraftig.woff2](https://cdn.openai.com/common/fonts/soehne/soehne-kraftig.woff2)\n- [KaTeX_Main-Regular.woff2](https://cdn.openai.com/common/fonts/katex/KaTeX_Main-Regular.woff2) (+ Main-Bold, Main-Italic, Main-BoldItalic)\n- [KaTeX_Math-Italic.woff2](https://cdn.openai.com/common/fonts/katex/KaTeX_Math-Italic.woff2) (+ Math-BoldItalic)\n- [KaTeX_Size2-Regular.woff2](https://cdn.openai.com/common/fonts/katex/KaTeX_Size2-Regular.woff2) (+ Size1, Size3, Size4)\n- [KaTeX_Caligraphic-Regular.woff2](https://cdn.openai.com/common/fonts/katex/KaTeX_Caligraphic-Regular.woff2) (+ Caligraphic-Bold)\n\n**Earlier list of fonts that are no longer accessible:**\n\n- ~~[Signifier-Regular.otf](https://chat.openai.com/fonts/Signifier-Regular.otf)~~\n- ~~[Sohne-Buch.otf](https://chat.openai.com/fonts/Sohne-Buch.otf)~~\n- ~~[Sohne-Halbfett.otf](https://chat.openai.com/fonts/Sohne-Halbfett.otf)~~\n- ~~[SohneMono-Buch.otf](https://chat.openai.com/fonts/SohneMono-Buch.otf)~~\n- ~~[SohneMono-Halbfett.otf](https://chat.openai.com/fonts/SohneMono-Halbfett.otf)~~\n- ~~[KaTeX_Caligraphic-Bold.woff](https://chat.openai.com/fonts/KaTeX_Caligraphic-Bold.woff) (_Caligraphic-Regular_ for Regular font)~~\n- ~~[KaTeX_Fraktur-Bold.woff](https://chat.openai.com/fonts/KaTeX_Fraktur-Bold.woff) (_Fraktur-Regular_ for Regular font)~~\n- ~~[KaTeX_Main-Bold.woff](https://chat.openai.com/fonts/KaTeX_Main-Bold.woff) (_BoldItalic_, _Italic_, _Regular_ for font weights you can probably guess)~~\n- ~~[KaTeX_Math-Bold.woff](https://chat.openai.com/fonts/KaTeX_Math-Bold.woff) (_BoldItalic_, _Italic_, _Regular_ for font weights you can probably guess)~~\n- ~~[KaTeX_SansSerif-Bold.woff](https://chat.openai.com/fonts/KaTeX_SansSerif-Bold.woff) (_Italic_, _Regular_ for font weights you can probably guess)~~\n- ~~[KaTeX_Script-Regular.woff](https://chat.openai.com/fonts/KaTeX_Script-Regular.woff)~~\n- ~~[KaTeX_Size1-Regular.woff](https://chat.openai.com/fonts/KaTeX_Size1-Regular.woff) (_Size1_, _Size2_, _Size3_, _Size4_)~~\n- ~~[KaTeX_Typewriter-Regular.woff](https://chat.openai.com/fonts/KaTeX_Typewriter-Regular.woff)~~\n\n## Application\nChatGPT is a NextJS application. Server information cannot be clearly found as the entirety of chat.openai.com is routed through Cloudflare. Sentry Analytics are requested ~~for the Thumbs Up/Thumbs Down feedback the user selects for a message~~ periodically. Statsig is attempted to be loaded but CORS blocks it due to the Same Origin Policy **(actually an effect of uBlock Origin)**.\n\n## Data\n### Session data\nA request can be made to `/api/auth/session` (without the `Authorization` header) to access data like the following:\n\n```\nuser: (Object)\n|__ id: \"user-[redacted]\"\n|__ name: \"[redacted]@[redacted].com\"\n|__ email: \"[redacted]@[redacted].com\"\n|__ image: \"https://s.gravatar.com/avatar/[MD5 hash of account email address]?s=480\u0026r=pg\u0026d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fte.png\"\n|__ picture: \"https://s.gravatar.com/avatar/[MD5 hash of account email address]?s=480\u0026r=pg\u0026d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fte.png\"\n|__ idp: \"auth0\"\n|__ iat: 1690111234\n|__ mfa: [redacted]\n|__ groups: (Array)\n|__ intercom_hash: \"[redacted]\"\nexpires: \"2023-08-01T23:45:12.345Z\"\naccessToken: \"ey..[redacted]..\"\nauthProvider: \"auth0\"\n```\n\n### User data\nThis requires an access token passed through the `Authorization` header, so this cannot be accessed using your browser directly, but here's what we have when we make a request to `/backend-api/accounts/check/v4-2023-04-27` ~~(that URL's gonna be a regular pain to update)~~:\n\n```\naccounts: (Object)\n|__ default: (Object)\n|____ account: (Object)\n|______ account_user_role: \"account-owner\"\n|______ account_user_id: \"92[redacted]40\"\n|______ processor: (Object)\n|________ a001: (Object)\n|__________ has_customer_object: false\n|________ b001: (Object)\n|__________ has_transaction_history: false\n|______ account_id: \"34[redacted]71\"\n|______ is_most_recent_expired_subscription_gratis: false\n|______ has_previously_paid_subscription: false\n|______ name: null\n|______ structure: \"personal\"\n|____ features: (Array)\n|______ \"log_statsig_events\"\n|______ \"log_intercom_events\"\n|______ \"new_plugin_oauth_endpoint\"\n|______ \"arkose_enabled\"\n|______ \"infinite_scroll_history\"\n|______ \"model_switcher_upsell\"\n|______ \"shareable_links\"\n|______ \"layout_may_2023\"\n|______ \"dfw_message_feedback\"\n|______ \"ios_disable_citation_menu\"\n|______ \"dfw_inline_message_regen_comparison\"\n|____ entitlement: (Object)\n|______ subscription_id: null\n|______ has_active_subscription: false\n|______ subscription_plan: \"chatgptfreeplan\"\n|______ expires_at: null\n|____ last_active_subscription: (Object)\n|______ subscription_id: null\n|______ purchase_origin_platform: \"chatgpt_not_purchased\"\n|______ will_renew: false\n```\n\nThe returned data is different if you use ChatGPT Plus.\n\n### User data (using ~~chat.json~~ [chatId].json)\nWhen we make a request to `/_next/data/[build ID]/c/[conversation ID].json?chatId=[conversation ID]` (can be done in the browser, cannot be done without authentication), we get a response like this:\n```\npageProps:\n|__ user (Object):\n|____ id: user-[redacted]\n|____ name: [redacted]@[redacted].com\n|____ email: [redacted]@[redacted].com\n|____ image: https://s.gravatar.com/avatar/8c[redacted in case of possible unique identifier]c7?s=480\u0026r=pg\u0026d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2F[first two letters of email address].png\n|____ picture: https://s.gravatar.com/avatar/8c[redacted in case of possible unique identifier]c7?s=480\u0026r=pg\u0026d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2F[first two letters of email address].png\n|____ groups: []\n|__ serviceStatus: {}\n|__ userCountry: [redacted two letter country code]\n|__ geoOk: false\n|__ isUserInCanPayGroup: true\n|__ __N_SSP: true\n```\n\nThis is the some of the same data (excluding accessToken and expires, both relevant to an access token) you get using the method in [Session data](#session-data) except you also get info about the country the user is located in and whether ChatGPT Plus is available in their location.\n\n**EDIT:** When ChatGPT returns a message like \"_We're experiencing exceptionally high demand. Please hang tight as we work on scaling our systems._\", `serviceStatus` looks like this:\n```\ntype: warning\nmessage: We're experiencing exceptionally high demand. Please hang tight as we work on scaling our systems.\noof: true\n```\nI didn't make up the `oof` variable, that is actually part of the response 😂\n\n### Model data\n_This section has been corrected as per [issue #8](https://github.com/terminalcommandnewsletter/everything-chatgpt/issues/8) created by [@0xdevalias (on GitHub)](https://github.com/0xdevalias)._\n\nWhat model does ChatGPT use? Well, just query `/backend-api/models`!\n```\nmodels: (Array)\n|__ (Object)\n|____ slug: \"text-davinci-002-render-sha\"\n|____ max_tokens: 8191\n|____ title: \"Default (GPT-3.5)\"\n|____ description: \"Our fastest model, great for most everyday tasks.\"\n|____ tags: (Array)\n|______ \"gpt3.5\"\n|____ capabilities: (Object)\n|____ product_features: (Object)\n categories: (Array)\n|__ (Object)\n|____ category: \"gpt_3.5\"\n|____ human_category_name: \"GPT-3.5\"\n|____ subscription_level: \"free\"\n|____ default_model: \"text-davinci-002-render-sha\"\n|____ browsing_model: \"text-davinci-002-render-sha-browsing\"\n|____ code_interpreter_model: \"text-davinci-002-render-sha-code-interpreter\"\n|____ plugins_model: \"text-davinci-002-render-sha-plugins\"\n```\n\n(There are more models if you use ChatGPT Plus, as shown in [issue #8](https://github.com/terminalcommandnewsletter/everything-chatgpt/issues/8), but this is what a Free user would see.)\n\n### Beta Features Settings\n_Thanks to [@0xdevalias (on GitHub)](https://github.com/0xdevalias) for creating [issue #7](https://github.com/terminalcommandnewsletter/everything-chatgpt/issues/7) about this feature._\n\nOn page load (as a Plus user), a request is made to `/backend-api/settings/beta_features`. This returns a response similar to this:\n```\nbrowsing: false\nchat_preferences: true\ncode_interpreter: true\nplugins: true\n```\n\nThe `browsing` key seems to refer to \"Browse with Bing\" (a feature disabled from public access currently, likely why it's set to `false` in the above data).\n\nThe `chat_preferences` key refers to Custom Instructions, a new feature allowing users to set custom details persistent across chats.\n\nThe `code_interpreter` key refers to the Code Interpreter feature which allows GPT to run code in a Python sandbox.\n\nThe `plugins` key refers to ChatGPT Plugins.\n\n### Disabling/Enabling \"Chat History \u0026 Training\"\nWhen you click your name/email address in the bottom-left corner of the screen (on desktop) \u003e Settings \u003e Show (next to Data Controls) \u003e toggle next to Chat History and Training, the following happens:\n\nFirst, [the list of conversations is requested](#conversation-history).\n\nThen we make a request to the same path as [Model data](#model-data), except a query parameter is added to the URL `?history_and_training_disabled=true` or `?history_and_training_disabled=false` depending on whether the setting is disabled or enabled respectively.\n\nThen, we request `/_next/data/[build ID]/index.json` (with the same data as [[chatId].json](#user-data-using-chatjson-chatidjson)).\n\n### Data Export\nWhen you use the \"Export data\" feature to export your data, a POST request is made to `/backend-api/accounts/data_export` with no request body and the response of `status: \"queued\"`.\n\nAs the name suggests, a data export is sent by email.\n\nThe data export is a `.zip` file containing `user.json`, `conversations.json`, `message_feedback.json`, `model_comparisons.json`, `chat.html`.\n\nThe data in `user.json` looks like this:\n```json\n{\"id\": \"user-[redacted]\", \"email\": \"[redacted]@[redacted].com\", \"chatgpt_plus_user\": false, \"phone_number\": \"+[redacted]\"}\n```\n\nSample data for `model_comparisons.json` is in [sample/model_comparisons.json](./sample/model_comparisons.json)\n\nSample data for `message_feedback.json`:\n```json\n[{\"message_id\": \"[redacted]\", \"conversation_id\": \"[conversationidwithoutdashes]\", \"user_id\": \"user-[redacted]\", \"rating\": \"thumbsUp\", \"content\": \"{\\\"text\\\": \\\"This is a test.\\\"}\"}]\n```\n\nSample data for `conversations.json` is in [sample/conversations.json](./sample/conversations.json)\n\n`chat.html` is a page that dynamically (using client-side JS) displays entire chat history for every conversation saved using conversation data (stored in the file) similar to that from `conversations.json`. You can find a sample in [sample/chat.html](./sample/chat.html)\n\n\n## Conversation\n### Conversation History\nConversation history can be accessed (again, requires an access token, which seems to be the Authorization header) at `/backend-api/conversations?offset=0\u0026limit=28` (the web interface limits it to 28 chats) which returns something like this:\n```\nitems: []\nlimit: 28\noffset: 0\ntotal: 0\n```\nIt doesn't work because ChatGPT is having some issues at the time of writing:\n\u003e \"_Not seeing what you expected here? Don't worry, your conversation data is preserved! Check back soon._\"\n\nBut this is probably what a person new to ChatGPT sees.\n\n**EDIT: If you log out and log back in, history works just fine. So, here's what I see**\n\n```\nitems (array)\n|__ (each conversation is an object)\n|____ id: [redacted conversation ID]\n|____ title: [conversation title]\n|____ create_time: 2023-03-09THH:MM:SS.MILLIS\n|__...\ntotal: [number of conversations] (can be greater than 28)\nlimit: 28\noffset: 0 (can be set to a higher number and it returns the conversations after that index, starting from 0)\n```\n\n**After 28 conversations listed, the ChatGPT UI shows a `Show more` button which sends a request with `offset=28`**\n\n### Getting the Conversation ID\nSpeaking of ChatGPT conversation history not being available, we can get the Conversation ID pretty easily (to someone who is familiar with DevTools, that is)\n\nWhy? Because ChatGPT forces you into a ~~/chat~~ `/` path for a new conversation, creates a conversation, **BUT DOESN'T CHANGE THE URL**. This is also helpful when chat history isn't available.\n\n1. We get the Conversation ID using DevTools (this requires a message to be sent)\n![A ChatGPT window with Firefox DevTools open. In the list of requests, a request with the conversation ID can be seen. In addition, a request to a moderations endpoint has a response containing the conversation ID, along with the user's entered text 'How can I say \"MOOOOOOOOOOOOOOOOOOO\" as a cow in the terminal?'](./images/Getting-Conversation-ID.png)\n2. Then, we visit ~~`https://chat.openai.com/chat/\u003cchat ID here\u003e`~~ `https://chat.openai.com/c/\u003cchat ID here\u003e`.\n\n### Loading a Past Conversation\nWhen the user clicks on a past conversation, a request is made (requiring an access token, ~~likely the cookie with other factors to ensure genuine requests~~ an Authorization header) to `/backend-api/conversation/\u003cconversation ID\u003e` with a response like this:\n\n```\ntitle: \u003cTitle of Conversation\u003e\ncreate_time: EPOCHEPOCH.MILLIS\nmapping (Object)\n|__ \u003cmessage ID\u003e (Array):\n|____ id: \u003cmessage ID\u003e\n|____ message (Object):\n|______ id: \u003cmessage ID\u003e\n|______ author (Object):\n|________ role: system (First message) | user | assistant\n|________ metadata: (Empty object)\n|______ create_time: EPOCHEPOCH.MILLIS \n|______ content (Object):\n|________ content_type: text\n|________ parts: [\"\"]\n|______ end_turn: true (system) | false\n|______ weight: 1.0\n|______ metadata: {}\n|______ recipient: all\n|____ parent: \u003cparent message ID\u003e\n|____ children (Array): \u003cchild message ID(s)\u003e\n```\n\n### The process of asking ChatGPT a question\n_This section has been corrected as per [issue #4](https://github.com/terminalcommandnewsletter/everything-chatgpt/issues/4) created by [@Snarik (on GitHub)](https://github.com/Snarik)._\n\nLet's say I ask ChatGPT a question `\"What is ChatGPT?\"`. First, we make a POST request to `/backend-api/conversation` with a request body like this:\n```\naction: next\nmessages (Array):\n|__ (Object):\n|____ author (Object):\n|______ role: user\n|____ content (Object):\n|______ content_type: text\n|______ parts (Array):\n|________ What is ChatGPT?\n|__ id: 0c[redacted]91\n|__ role: user\nmodel: text-davinci-002-render-sha\nparent_message_id: a0[redacted]7f\n```\n\nThis responds with an EventStream which ends with a `[DONE]` signal. You can view a sample response in [sample/conversation-event-stream.txt](./sample/conversation-event-stream.txt).\n\nThen [we get a list of past conversations](#conversation-history) that includes one \"New chat\".\n\nThen we make a request to `/backend-api/moderations` with a request body like this:\n\n```\nconversation_id: 05[redacted]2d\ninput:\tWhat is ChatGPT?\nmessage_id: 0c[redacted]91\nmodel: text-moderation-playground\n```\n\nThat returns a response like this:\n\n```\nflagged:\tfalse\nblocked:\tfalse\nmoderation_id\tmodr-6t[redacted]Bk\n```\n\nThen we make a request to `/backend-api/conversation/gen_title/\u003cconversation ID\u003e` with the request body like this:\n```\nmessage_id: c8[redacted]0e\nmodel: text-davinci-002-render-sha\n```\n\nThat gets a response like this:\n```\ntitle: \u003ctitle for conversation\u003e\n```\n\nThen we make **another** request to `/backend-api/moderations` with a request body that includes the AI response (marked as `\u003cAI response\u003e`) looking like this:\n\n```\ninput: \\nWhat is ChatGPT?\\n\\n\u003cAI response\u003e\nmodel: text-moderation-playground\nconversation_id: 05[redacted]2d\nmessage_id: c8[redacted]0e\n```\n\nThat gets a response in the exact same format as the previous request made to this path.\n\nThen [we **finally** get a list of past conversations](#conversation-history) including the proper title of the chat that appears on the sidebar.\n\n### (Soft)Deleting a conversation\nWhen you click Delete on a conversation, a PATCH request is made to `/backend-api/conversation/05[redacted]2d` with the body `is_visible: false` and gets a response of `success: true` back. This implies that a conversation is being soft-deleted, not deleted on their systems.\n\nThen (not sure why), we request `/_next/data/[build ID]/index.json` (with the same data as [[chatId].json](#user-data-using-chatjson-chatidjson)).\n\nAfter that, we [get the list of conversations that appear on the sidebar](#conversation-history).\n\n### Can you revive a conversation?\nI had a question after the above section - can you revive a conversation by setting the request body to `is_visible: true`? The answer is **nope**, you can't. This just returns a 404 with the response `detail: Can't load conversation 94[redacted]9b`. But if you don't [get the list of conversations again](#conversation-history), you can still access the conversations. Although, trying to get a response from ChatGPT, you get a [Conversation not found](#conversation-not-found) error.\n\n### Clearing Conversations\nI was a bit unsure if I should do this. But I looked through and did it anyway. (The below is almost a one-to-one copy of [(Soft)Deleting a conversation](#softdeleting-a-conversation), with minor changes)\n\nWhen you click Delete on a conversation, a PATCH request is made to `/backend-api/conversations` (conversation**s** rather than conversatio**n/05[redacted]2d**) with the body `is_visible: false` and gets a response of `success: true` back. This implies that conversations are being soft-deleted, not deleted on their systems.\n\nThen (not sure why), we request `/_next/data/[build ID]/index.json` (with the same data as [[chatId].json](#user-data-using-chatjson-chatidjson)).~~\n\nAfter that, we [get the list of conversations that appear on the sidebar](#conversation-history).\n\n**Something funny:** If ChatGPT history is temporarily unavailable (returning an empty response), the app shows a message. But if your ChatGPT conversation history is blank anyway, you just see a message that history is temporarily unavailable.\n\n### Leaving Feedback on Messages (Thumbs Up/Thumbs Down)\nWhen you click the thumbs up/thumbs down button on a message, a POST request is made to `/backend-api/conversation/message_feedback` with the request body like this:\n```\nconversation_id: 94[redacted]9b\nmessage_id: 96[redacted]b7\nrating: thumbsUp | thumbsDown\n```\nThat receives a response like this:\n```\nmessage_id: 96[redacted]b7\nconversation_id: 94[redacted]9b\nuser_id: user-[redacted]\nrating: thumbsUp | thumbsDown\ncontent: {}\n```\n\nThen, when you type feedback and click submit, a request is made to the same path with a request body like this:\n```\nconversation_id: 94[redacted]9b\nmessage_id: 96[redacted]b7\nrating: thumbsUp\ntags: [] (for thumbsDown, an array containing any or all of these: harmful, false, not-helpful)\ntext: \u003cFeedback here\u003e\n```\nWith a response similar to the one above, with only the `content` field different:\n```\nmessage_id: 96[redacted]b7\nconversation_id: 94[redacted]9b\nuser_id: user-[redacted]\nrating: thumbsUp\ncontent: '{\"text\": \"\u003cFeedback here\u003e\"}' |'{\"text\": \"This is solely for testing purposes. You can safely ignore this feedback.\", \"tags\": [\"harmful\", \"false\", \"not-helpful\"]}' (This is for a thumbsDown review)\n```\n\n### Leaving Feedback (on Regenerated Responses)\nWhen you regenerate a response, you get a feedback box like this:\n![Feedback box with the text \"Was this response better or worse?\" abd three buttons \"Better\", \"Worse\" and \"Same\"](./images/regenerated-response-feedback.png)\n\nThe request body looks like this:\n```\ncompare_step_start_time: 1679[redacted]\ncompletion_comparison_rating: new (for Better) | original (for Worse) | same (for Same)\nconversation_id: c7[redacted]f0\nfeedback_start_time: 1679[redacted]\nfeedback_version: inline_regen_feedback:a:1.0\nfrontend_submission_time: 1679[redacted]\nnew_completion_load_end_time: 1679[redacted]\nnew_completion_load_start_time: 1679[redacted]000\nnew_completion_placement: not-applicable\nnew_message_id: 7b[redacted]4a\noriginal_message_id: eb[redacted]e2\nrating: none\ntags: []\ntext: \"\"\n```\n\nThat returns an empty response.\n\n### Renaming Conversations\nWhen we rename a conversation, a PATCH request is made to `/backend-api/conversation/27[redacted]1d` with the request body like `{title: New Title}` and the response `{success:true}`.\n\nThen, [we get the list of conversations](#conversation-history) that contains the new title.\n\n### Continuing a ChatGPT response\nWhen we click `Continue response`, a `POST` request is made to `/backend-api/conversation` with a request body like this:\n```\naction: \"continue\"\nconversation_id: \"63[redacted]a8\"\nhistory_and_training_disabled: false\nmodel: \"text-davinci-002-render-sha\"\nparent_message_id: \"af[redacted]67\"\nsupports_modapi: true\ntimezone_offset_min: [minutes offset]\n```\n\nwhich returns an EventStream with lots of data like this:\n\n```\ndata: {\\\"message\\\": {\\\"id\\\": \\\"ad[redacted]04\\\", \\\"author\\\": {\\\"role\\\": \\\"assistant\\\", \\\"name\\\": null, \\\"metadata\\\": {}}, \\\"create_time\\\": EPOCHEPOCH.MILLIS, \\\"update_time\\\": null, \\\"content\\\": {\\\"content_type\\\": \\\"text\\\", \\\"parts\\\": [\\\"\u003cinsert message here\u003e\\\"]}, \\\"status\\\": \\\"in_progress\\\", \\\"end_turn\\\": null, \\\"weight\\\": 1.0, \\\"metadata\\\": {\\\"message_type\\\": \\\"next\\\", \\\"model_slug\\\": \\\"text-davinci-002-render-sha\\\"}, \\\"recipient\\\": \\\"all\\\"}, \\\"conversation_id\\\": \\\"84[redacted]25\\\", \\\"error\\\": null}\n```\n\n### Sharing Conversations\nWhen the share button next to the conversation is clicked, a modal appears which sends a `POST` request to `/backend-api/share/create` with a request body like this:\n```\nconversation_id: \"5a[redacted]5e\"\ncurrent_node_id: \"1d[redacted]25\"\nis_anonymous: true | false (depending on whether \"Share anonymously\" or \"Share with name\" is chosen)\n```\nand a response like this:\n```\nshare_id: \"37[redacted]05\"\nshare_url: \"https://chat.openai.com/share/37[redacted]05\"\ntitle: \"\u003ctitle here\u003e\"\nis_public: false\nis_visible: true\nis_anonymous: true\nhighlighted_message_id: null\ncurrent_node_id: \"1d[redacted]25\"\nalready_exists: false\nmoderation_state: {\n|__has_been_moderated: false\n|__has_been_blocked: false\n|__has_been_accepted: false\n|__has_been_auto_blocked: false\n|__has_been_auto_moderated: false\n}\n```\n\nWhen `Copy link` is clicked, a `PATCH` request is sent to `/backend-api/share/[conversation_id]` with a body like this (I selected \"Share with name\" which isn't reflected in the previous request):\n```\nhighlighted_message_id: null\nis_anonymous: false\nis_public: true\nis_visible: true\nshare_id: \"37[redacted]05\"\ntitle: \"\u003ctitle here\u003e\"\n```\nWhich receives a response like this:\n```\nmoderation_state: {\n  has_been_moderated: false\n  has_been_blocked: false\n  has_been_accepted: false\n  has_been_auto_blocked: false\n  has_been_auto_moderated: false\n}\n```\n\nVisiting the URL returns pre-rendered HTML of the conversation, with stylesheets being added after.\n\n### Continuing a Shared Conversation\n\nWhen clicking `Continue conversation`, a request is made to `/_next/data/[build ID]/share/37[redacted]05/continue.json?shareParams=37[redacted]05\u0026shareParams=continue` with no request data and a *very* long response including data similar to that from [User data (using [chatId].json)](#user-data-using-chatjson-chatidjson) as well as data about the conversation shared.\n\n### Listing Shared Conversations\nA list of shared conversations can be found by sending a `GET` request (with the Authorization header to your auth token) to `/backend-api/shared_conversations?order=created` (without a request payload) which can return output like this:\n```\n items: (Array)\n|__ (Object)\n|____ id: \"37[redacted]05\"\n|____ title: \"\u003ctitle here\u003e\"\n|____ create_time: \"2023-06-DDTHH:MM:SS.MILLIS+00:00\"\n|____ update_time: \"2023-06-DDTHH:MM:SS+00:00\"\n|____ mapping: null\n|____ current_node: null\n|____ conversation_id: \"5a[redacted]5e\"\n total: 1\n limit: 50\n offset: 0\n has_missing_conversations: false\n```\n\n### Deleting a Shared Conversation\nWhen you delete a shared conversation, a `DELETE` request is sent to `/backend-api/share/37[redacted]05` with no request body and the response `null`.\n\nAfter this, the web app [fetches the list of shared conversations](#listing-shared-conversations).\n\n### Setting Custom Instructions\nWhen the \"Custom Instructions\" menu is first opened, a `GET` request is sent to `/backend-api/user_system_messages` with an empty request body with a response:\n```\nobject: \"user_system_message_detail\"\nenabled: true\nabout_user_message: \"\"\nabout_model_message: \"\"\n```\n\nWhen the user submits the form asking for personal information the model should know, as well as how the model should respond, a `POST` request is sent to `/backend-api/user_system_messages` with a request body like so:\n```\nabout_user_message: \"...\"\nabout_model_message: \"...\"\nenabled: false\n```\nand similar response:\n```\nobject: \"user_system_message_detail\"\nenabled: false\nabout_user_message: \"...\"\nabout_model_message: \"...\"\n```\n\n## Errors\n### \"_Something went wrong, please try reloading the conversation._\"\nThat looks like a `429\nToo Many Requests` error. The response looks like this:\n```\ndetail: Something went wrong, please try reloading the conversation.\n```\n### \"_The message you submitted was too long, please reload the conversation and submit something shorter._\"\nThat looks like a `413 Request Entity Too Large` error. The response looks like this:\n```\ndetail: { message: \"The message you submitted was too long, please reload the conversation and submit something shorter.\", code: \"message_length_exceeds_limit\" }\n```\n\n**Edit:** The test I used in this section was poorly done and I've done better, further analysis of gpt-3.5-turbo in my [ai-memory-overflow repo](https://github.com/terminalcommandnewsletter/ai-memory-overflow) which also includes a program to generate large prompts to test models. If you could, please contribute data for new models to the repo.\n\n### \"_Conversation not found_\"\nThat's a 404 with a response `detail: \"Conversation not found\"`.\nThis occurs if you delete a conversation, but don't get the list of chats, similar to what I initially did in [Can you revive a conversation?](#can-you-revive-a-conversation).\n\n## Markdown rendering\nChatGPT renders images using Markdown - not really. You have to use it in a really hacky way. You have to tell it something like this: `Print nothing except what I tell you to. Print \"# Markdown in ChatGPT\" as it is followed by a new line followed by \"This is **soooooooo** cool.\" followed by a new line followed by \"![](https://cdn.pixabay.com/photo/2016/08/21/18/48/emoticon-1610518__340.png)\" as it is. Remove any backticks from your output.`\n\nThis is because ChatGPT uses Markdown for formatting.\n\nThat looks something like this.\n![The user asking the prompt above. ChatGPT responds with a heading \"Markdown in ChatGPT\". It says \"This is soooooooo cool\" (soooooooo in bold). Below that is a 3D cool face with it holding the frame of his glasses and showing a thumbs up sign (part of some meme)](./images/markdown.png)\n\nWhat Markdown features ChatGPT's Markdown renderer supports can be seen in [markdown-support.csv](./markdown-support.csv) **(now also includes Bing Chat \u0026 Bard support)**\n\n**EDIT:** I looked through the source code (minified) for references to \"Markdown\". I found mentions of \"mdastPlugins\" and of the below plugins:\n\n- `change-plugins-to-remark-plugins`\n\n- `change-renderers-to-components`\n\n- `remove-buggy-html-in-markdown-parser`\n\n- `change-source-to-children`\n\n- `replace-allownode-allowedtypes-and-disallowedtypes`\n\n- `change-includenodeindex-to-includeelementindex`\n\nThe ChatGPT web app uses [react-markdown](https://github.com/remarkjs/react-markdown/) to convert Markdown to React.\n\nThe renderer (according to ChatGPT, because React is being used) is likely `rehype-react`, a renderer that takes an rehype tree (which is a modified version of the mdast tree) and converts it into a React component hierarchy. It allows you to define custom React components for each type of HTML element, which gives you full control over how the Markdown content is rendered in your application.\n\n`react-markdown` is built on top of `rehype-react` and provides a higher-level interface for rendering Markdown content in a React application. It handles the parsing of Markdown content into an `mdast` tree using `remark`, and then passes the `mdast` tree to `rehype-react` for rendering as React components.\n\n(The 2 paragraphs above were written by ChatGPT.)\n\n## ChatGPT Plus\n### GPT-4 for Free Users? (nope)\nGPT-4 was released in early March of 2023. I noticed that in videos of Plus subscribers using GPT-4, the URL ended with `?model=gpt-4`. So I was wondering if one could just add this to the end of the URL and get access to GPT-4. As expected, **you can't**. [Every message sent](#the-process-of-asking-chatgpt-a-question) uses [`text-davinci-002-render-sha`](#model-data).\n\n### Access ChatGPT when it's down\n\n\u003e **Warning**\n\u003e I haven't tried it any more than this one time I recorded it (ChatGPT doesn't go down very often these days) so I'm not entirely certain whether this will work for you, but it's worth a shot!\n\nWhen ChatGPT is down, you get a screen telling you that ChatGPT is down (with an entertaining message from a [fixed list](./chatgpt-down-messages.txt)) **and an input field for Plus subscribers to get a personalised login link**. Could a non-Plus subscriber type in their email, click `Send link` and access ChatGPT? That would result in an email not being se-\n![A GIF of a user with the email sent, showing the request, and having a link in their email](./images/chatgpt-plus-login-link.gif)\n\nThis works by sending a request to `/backend-api/bypass/link` with the request body `email: \u003cemail\u003e` and the response `status: success`.\n\n## Rendering Markdown _inside_ a code block\nI was asking ChatGPT to render images from Unsplash (using a URL and Markdown) based on my queries. Then, the image from the URL appeared for a split second before disappearing. I'm assuming that this is because of the Markdown renderer assuming that as Markdown until the code block was closed.\n\n![A GIF showing ChatGPT typing out a code block with Markdown for rendering an image and it rendering an image for a split second before swapping back to the code block](./images/Markdown-in-code-block-rendered.gif)\n\n## Statsig Feature Gates\nWhen the page is loaded (without uBlock Origin), a request is made to `https://featuregates.org/v1/initialize` with a body consisting of reversed Base64 with data like this:\n```\n{\"user\":{\"userID\":\"user-[redacted]\",\"privateAttributes\":{\"email\":\"[redacted]@[redacted].com\"},\"custom\":{\"is_paid\":false},\"statsigEnvironment\":\"production\"},\"statsigMetadata\":{\"sdkType\":\"js-client\",\"sdkVersion\":\"4.32.0\",\"stableID\":\"7a4[redacted]07e\"},\"sinceTime\":[a few hours before I accessed ChatGPT in Epoch time in milliseconds]}\n```\n\nThat gives us a response like this:\n```\n{\"feature_gates\":{},\"dynamic_configs\":{\"tZk[redacted]+Q=\":{\"name\":\"tZk[redacted]+Q=\",\"value\":{},\"rule_id\":\"prestart\",\"group\":\"prestart\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"Lnn[redacted]IwY=\":{\"name\":\"Lnn[redacted]IwY=\",\"value\":{},\"rule_id\":\"prestart\",\"group\":\"prestart\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"QSf[redacted]t64=\":{\"name\":\"QSf[redacted]t64=\",\"value\":{\"prompt_enabled\":true},\"rule_id\":\"61h[redacted]fSc\",\"group\":\"61h[redacted]fSc\",\"is_device_based\":false,\"is_experiment_active\":true,\"is_user_in_experiment\":true,\"secondary_exposures\":[]},\"JhJ[redacted]k1w=\":{\"name\":\"JhJ[redacted]k1w=\",\"value\":{},\"rule_id\":\"prestart\",\"group\":\"prestart\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"PFe[redacted]3yc=\":{\"name\":\"PFe[redacted]3yc=\",\"value\":{\"enable_v0_comparison_modal\":true,\"enable_v0_inline_regen_comparisons\":true},\"rule_id\":\"launchedGroup\",\"group\":\"launchedGroup\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"9wf[redacted]T1g=\":{\"name\":\"9wf[redacted]T1g=\",\"value\":{\"use_tz_offset\":true},\"rule_id\":\"launchedGroup\",\"group\":\"launchedGroup\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"oDt[redacted]lQ4=\":{\"name\":\"oDt[redacted]lQ4=\",\"value\":{},\"rule_id\":\"prestart\",\"group\":\"prestart\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]}},\"layer_configs\":{},\"sdkParams\":{},\"has_updates\":true,\"generator\":\"scrapi-nest\",\"time\":[same timestamp from request],\"evaluated_keys\":{\"userID\":\"user-[redacted]\",\"stableID\":\"7a4[redacted]07e\"}}\n```\n\nBefore you ask, I tried decoding every single Base64 string you can see above and it just had some random characters with control characters interjected.\n\nThen we request `https://events.statsigapi.net/v1/rgstr` with the body like this:\n```\n{\"events\":[{\"eventName\":\"statsig::diagnostics\",\"user\":{\"userID\":\"user-[redacted]\",\"custom\":{\"is_paid\":false},\"statsigEnvironment\":\"production\"},\"value\":null,\"metadata\":{\"context\":\"initialize\",\"markers\":[{\"key\":\"overall\",\"step\":null,\"action\":\"start\",\"value\":null,\"timestamp\":3768},{\"key\":\"initialize\",\"step\":\"network_request\",\"action\":\"start\",\"value\":null,\"timestamp\":3769},{\"key\":\"initialize\",\"step\":\"network_request\",\"action\":\"end\",\"value\":200,\"timestamp\":4639},{\"key\":\"initialize\",\"step\":\"process\",\"action\":\"start\",\"value\":null,\"timestamp\":4640},{\"key\":\"initialize\",\"step\":\"process\",\"action\":\"end\",\"value\":null,\"timestamp\":4641},{\"key\":\"overall\",\"step\":null,\"action\":\"end\",\"value\":null,\"timestamp\":4642}]},\"time\":[when I  accessed ChatGPT],\"statsigMetadata\":{\"currentPage\":\"https://chat.openai.com/chat\"}}],\"statsigMetadata\":{\"sdkType\":\"js-client\",\"sdkVersion\":\"4.32.0\",\"stableID\":\"7a4[redacted]07e\"}}\n```\n\nThat returns a 202 with a body of `{\"success\": true}`\n\nFor some reason, this request repeats after that.\n\n## ChatGPT Admin Panel\nI recently discovered an admin panel for ChatGPT (seemingly for an organization system) so I wrote what I found in [this Twitter thread](https://twitter.com/tercmd/status/1689642734829936640). This isn't public as of Aug 10, 2023.\n\n## Prompt Library\nChatGPT has some example prompts appear on the home screen. These are fetched by a `GET` request to `/backend-api/prompt_library/?limit=4\u0026offset=0` (requiring the `Authorization` header). The highest value for `limit` that returns a `200 OK` is `14`. The prompts returned each time are different. So, I used JS to send the same request a large number of times and then filter the unique ones. You can find all the prompts in [prompt-library.txt](./prompt-library.txt).\n\n## Conclusion\nThis is it. For now. As I see more details of ChatGPT, I'll add those in.\n\nCheck out [@OpenAI_Support](https://twitter.com/OpenAI_Support) (a **parody** account) for more OpenAI and ChatGPT related content.\n\nCheck me out on [Twitter](https://twitter.com/tercmd), or perhaps [my website (terminal-styled)](https://tercmd.com).\n\n[![Share on Twitter!](https://img.shields.io/badge/Share%20on%20Twitter-blue?style=for-the-badge\u0026logo=twitter\u0026logoColor=white)](https://twitter.com/intent/tweet?url=https%3A%2F%2Fl.tercmd.com%2FkJ9fS2)\n\n## License\n\u003ca rel=\"license\" href=\"https://creativecommons.org/licenses/by-sa/4.0/\"\u003e\u003cimg alt=\"Creative Commons License\" style=\"border-width:0\" src=\"https://i.creativecommons.org/l/by-sa/4.0/88x31.png\" /\u003e\u003c/a\u003e\u003cbr /\u003e\u003cspan xmlns:dct=\"https://purl.org/dc/terms/\" property=\"dct:title\"\u003eEverything ChatGPT\u003c/span\u003e by \u003ca xmlns:cc=\"https://creativecommons.org/ns#\" href=\"https://www.tercmd.com\" property=\"cc:attributionName\" rel=\"cc:attributionURL\"\u003etercmd.com\u003c/a\u003e is licensed under a \u003ca rel=\"license\" href=\"https://creativecommons.org/licenses/by-sa/4.0/\"\u003eCreative Commons Attribution-ShareAlike 4.0 International License\u003c/a\u003e.\n\nYou may find a copy of the license in the [`LICENSE`](./LICENSE) file.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterminalcommandnewsletter%2Feverything-chatgpt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fterminalcommandnewsletter%2Feverything-chatgpt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterminalcommandnewsletter%2Feverything-chatgpt/lists"}