Add x-super-properties header for user accounts#1507
Add x-super-properties header for user accounts#1507wavedevgit wants to merge 13 commits intoTyrrrz:primefrom
x-super-properties header for user accounts#1507Conversation
The x-super-properties header is an important header that contains info about the client with a launch signature. if this header is not provided, discord may flag requests and cause accounts to be banned/restricted
|
Insane this was never implemented until now. |
|
Have you tested this, and if so does it actually make a difference? Base-64 decoding the headers you used at https://gist.githubusercontent.com/MinerPL/731977099ca84bef7ad0a66978010045/raw/stable.headers.json (which, by the way, should maybe not be grabbed from an external link), there seem to be tokens unique to specific client instances. Here's a snippet: I worry that using hardcoded values here could either be meaningless or cause more flags. |
|
You're right that super props are essentially required to send alongside requests, but those values don't seem to be updated. You guys are free to use my API at |
|
You are right, I'll update the code right now to make the values unique. |
|
Btw, I did not test if this code works, as I currently have no way of doing so on Linux. Please verify that it works without any issues. |
|
This is still problematic, versions are out of date |
|
oh true, I guess i'll use the api you sent, thankss |
|
Crazy discord found some shit |
|
I updated it to use dolfie's api |
|
FWIW you're making a GET request to his api, while he suggested a POST request, which will give you the xsp data without the need to construct it yourself. |
|
I didn't read that correctly, I'll update the code right now |
|
Done |
|
I would not see it as wise to rely on a random web api to generate a user agent and x-super-properties, if it can be done by DCE itself easily |
x-super-properties header for user accounts
Generating your own properties seems weird too, I feel like that's very easily detectable :P |
|
Re-posting my message from the issue here so you can see my impl, I feel like getting the individual users properties could be a bit more beneficial (Webview2 container or something?) - This would also handle getting the token, which might be a benefit for less technical users.
|
There was a problem hiding this comment.
Pull request overview
Updates DiscordClient request behavior to more closely mimic a real browser (primarily for user-token requests), likely to reduce Discord anti-bot/anti-scraping detection.
Changes:
- Added
GenerateLaunchSignature()andGenerateUuid()helper functions near the top ofDiscordClient.cs. - Added logic in
DiscordClient.GetResponseAsync()to fetch browser-like header values from an external API and attach them to outgoing requests for non-bot tokens.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| // https://docs.discord.food/reference#launch-signature | ||
| static string GenerateLaunchSignature() | ||
| { | ||
| const string maskBinary = | ||
| "00000000100000000001000000010000000010000001000000001000000000000010000010000001000000000100000000000001000000000000100000000000"; | ||
|
|
||
| var mask = Convert.ToUInt128(maskBinary, 2); | ||
|
|
||
| var uuid = Guid.NewGuid().ToByteArray(); | ||
| var value = new UInt128(BitConverter.ToUInt64(uuid, 8), BitConverter.ToUInt64(uuid, 0)); | ||
|
|
||
| value &= ~mask; | ||
|
|
||
| Span<byte> bytes = stackalloc byte[16]; | ||
| BitConverter.TryWriteBytes(bytes[..8], (ulong)value.Lower); | ||
| BitConverter.TryWriteBytes(bytes[8..], (ulong)value.Upper); | ||
|
|
||
| return new Guid(bytes).ToString(); | ||
| } | ||
|
|
||
| static string GenerateUuid() | ||
| { | ||
| return Guid.NewGuid().ToString(); | ||
| } |
| string userAgent = proprties.GetProperty("user_agent").GetString()!; | ||
| string browserVersion = proprties.GetProperty("browser_version").GetString()!; |
| } | ||
| catch { } | ||
| } |
| var headers = new Dictionary<string, string> | ||
| { | ||
| ["sec-ch-ua-platform"] = $"\"{osType}\"", | ||
| ["referer"] = "https://discord.com/app", | ||
| ["x-debug-options"] = "bugReporterEnabled", | ||
| ["accept-language"] = "en-US,en;q=0.9", | ||
|
|
||
| ["sec-ch-ua"] = | ||
| $"\"Chromium\";v=\"{chromeMajor}\", \"Not;A=Brand\";v=\"99\"", | ||
|
|
||
| ["sec-ch-ua-mobile"] = "?0", | ||
|
|
||
| ["x-discord-timezone"] = "Europe/Warsaw", | ||
| ["x-context-properties"] = "eyJsb2NhdGlvbiI6Ii9hcHAifQ==", | ||
| ["x-discord-locale"] = "en-US", |
|
I feel like there are a lot of guesses/assumptions being thrown around here
I wouldn't exactly say it can be done "easily". You'd need to get the up-to-date client build number, which requires parsing discord's js files (whose format can change at any time). Of course it can be done, but it might be annoying to maintain.
It's not detectable as long as you do it correctly. It's what Dolfies's api does after all.
Why would it be more beneficial? As long as you generate valid ones there is virtually no difference. Extracting them from the webview could be problematic too. Btw, for your extension, it could be easier to grab and use discord's existing RestAPI class, which includes all necessary headers by default. Intercepting request headers sounds like an overkill. |
Yeah I've only just realized this after the fact :P It's fully working at the moment, I'll clean it up when I have some time over the next few days :> |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
anyone try this? |
|
Someone please try if this works lol |
|
Guys, I apologize for asking a beginner’s question. |
I can't say for sure, but this pr should fix the issue! |
Thank you for your kind responses. I’ll see what I can do. |
|
@wavedevgit Your code seems to have been AI generated and doesn't even build: |
|
I fixed this issue (yes the code was made using ai since I dont know csharp but I reviewed it to ensure quality of code) |
|
@wavedevgit Still doesn't seem to be fixed: EDIT: Building after fixing the variable at line 106. |
|
Can you please check now if it works? thank you btw |
|
@wavedevgit Probably not gonna work, since there is no Chances are this code won't really work and get my account banned, so I don't want to try any further. |
|
It's a curl -X POST https://cordapi.dolfi.es/api/v2/properties/web |
The up to date client build number can actually be parsed / fetched without searching through linked js files
dpy-self is made by the same author as the api host, the trust is there because it is their own dependency. It can just as likely go out of date in terms of parsing behaviour as when DCE would do it on its own. The only benefit is that the parsing mechanism can be changed from afar in case something changes in the future, the downside is that the parsing mechanism can be changed from afar and is dependent on a third party. Again, I don't see any benefit in using the web api in place for an algorithm / library. Edit: I shall also add, that I have nothing against @dolfies , for me personally it's all just about outweighing benefits vs disadvantages, and my bells are ringing when hearing that |
Yeah I've realized after posting that that GLOBAL_ENV has the build number now, my bad
You missed the point. The library + the api have been trustworthy and up-to-date for a long while as can be seen from the commits history and usage. Would you also distrust it if you were to use it as a regular
That is exactly the issue here though. From what I can tell, DCE's maintainer is not the type of person to watch discord's codebase for changes and apply fixes as soon as something breaks (look at how the tool didn't support forwarded messages until 2 weeks ago), let alone apply antispam preventions proactively. I'm not sure they are familiar with discord's antispam/selfbotting practices either, considering the tool has only sent |
Trust me, I have a fair share of that over at https://github.com/Tyrrrz/YoutubeExplode ;) Assuming the changes boil down to updating request headers or their values, I don't see why the community wouldn't be able to handle this.
I was familiar to the extent that was necessary for things to work, and, prior to recently, nothing beyond the
If you had reasons to believe that was insufficient, prior to the recent policies Discord introduced, then I must've missed it because I didn't see any issues/discussions raised by you.
Oh, I would love to delegate control over this to somebody else, but unfortunately control doesn't come without responsibility. And it's hard to take responsibility over an API, whose source code I haven't even seen (is there a GitHub repo somewhere?). It might be that we end up using that API in the end, but right now it's only clear what overhead it brings and not entirely clear how much effort it saves. |
|
@wavedevgit My apologies, it is indeed a 0001-Fix-adding-extra-request-headers.patch Thanks for your contributions. |
|
Thanks @svghubio for the fixed version |
| if (tokenKind != TokenKind.Bot) | ||
| { | ||
| try | ||
| await Task.Run(async () => |
There was a problem hiding this comment.
It's just to make sure the headers are added before the request is made (because of the async task)
There was a problem hiding this comment.
Task.Run doesn't help in any way with that. The request goes through only once Http.Client.SendAsync is executed. So the code before was already safe and wasn't at risk of running the request without the headers.
You force a background Task to be created via Task.Run and immediately await it, which effectively is a no-op here, with no other benefit 😄
Edit: Unless I am missing something that you are seeing
There was a problem hiding this comment.
I initially proposed this code. Sorry, I'm not the best at C# 😅
All I know is that with this await Task.Run(async () => it executes per every request just fine for me. Perhaps it could be omitted.
There was a problem hiding this comment.
Hm, should I revert that change?
While this is true, is it really a good enough reason to put the working of the whole project behind one single API that might, at some point in the future, without any prior notice, go offline? I say hardcoding a Also, not sure about the privacy aspect of forcing every single client to send a request to an unknown API that they don't even know they're reaching. |
|
The point of the API (at least for my use) is to make it easier to maintain props without having to push a release for every new field/minifier change/etc. It can definitely just be done in the project itself and should definitely be done as a fallback either way in case the API goes down for any period of time. I was just offering it as an option, it's up to the maintainers as to what they actually end up using :p |
|
Is there a released compiled version with this fix anywhere ? i see you want us to test it, it might make it easier. |
|
@tretretrer you can take the dev build produced from this branch: https://github.com/Tyrrrz/DiscordChatExporter/actions/runs/23216779809?pr=1507 |
|
thanks ill try right now |
As explained in the first commit description, the x-super-properties header is an important header that if not present may cause discord to flag requests or even worse ban/restrict accounts.
The added code uses this source to add headers that match a normal browser using the discord web client.
possibly closes #1497