What will be scraped
Explanation
We want to reverse engineer URL data
parameter:
# full url
https://poocoin.app/api2/candles-bsc?data=[YmLNHK6TU[Kblm4UXqKeF2FTYSSW2KsZ32XfnO6TU[KblJ1UVeONWKGSYebblF{U2S[fWqIVYeObmVzXYqCN1:VTUCQSGmOWHiWUWSCOl6VWU[OSFG2UVSCe2eqTYOKcYixZmetNFmrc4qOblG{TX25e2GYVnukcW[7Z4mKOlmrRkSTS2FyXXuHb1:IXUS[bl1zUVeSN16uVYiOb2qsVWSKfl2GXUSSb1[IUlSLcWqVRYeOblqFVnmKd1mucIWlS2[6[H2Hd1mrc3mOWG[1TXm4bWmuSoqbWYi4TXqwbV2J[{GQSWl1Uoq[OF6V[HiOSFqGUnqkNl2sWYeOWFG5XX2KNWG7VUKSWHirUWWXSV6FVlW[flVzTX5xQR%3E%3E
# data parameter
[YmLNHK6TU[Kblm4UXqKeF2FTYSSW2KsZ32XfnO6TU[KblJ1UVeONWKGSYebblF{U2S[fWqIVYeObmVzXYqCN1:VTUCQSGmOWHiWUWSCOl6VWU[OSFG2UVSCe2eqTYOKcYixZmetNFmrc4qOblG{TX25e2GYVnukcW[7Z4mKOlmrRkSTS2FyXXuHb1:IXUS[bl1zUVeSN16uVYiOb2qsVWSKfl2GXUSSb1[IUlSLcWqVRYeOblqFVnmKd1mucIWlS2[6[H2Hd1mrc3mOWG[1TXm4bWmuSoqbWYi4TXqwbV2J[{GQSWl1Uoq[OF6V[HiOSFqGUnqkNl2sWYeOWFG5XX2KNWG7VUKSWHirUWWXSV6FVlW[flVzTX5xQR%3E%3E
- data parameter contains token id, time interval, date, and limit argument which I believe is for candles amount to display.
Open dev tools, find relevant XHR request and go to JS source:
Format JavaScript code:
Go up in the stack trace to see the formation of data
URL argument:
Evaluate F
, W
, B
I
variables to understand what's happening:
B = w(476)
:
w()
returns function name:
var n = ["map", "70209pSjRdP", "13mXPpTk", "32970804XTFOSy", "33EDoYDa", "16914prTfjD", "charCodeAt", "680Pigxyq", "5194335PIAMSW", "stringify", "430dfxvAD", "21ASPctV", "&l=1", "4868dULKHq", "955100otFPGh", "substring", "QWRkcmVzcyI6IjB4MGM1REEwZjA3OTYyZGQwMjU2YzA3OTI0ODY", "4483450KFkYTE", "2303RvgaFj", "lpr", "host", "indexOf"];
function w(e, t) { return n[e - 467] }
I
contains base64 encoded characters shifted by one charater code to the right:
let obfuscatedFunctionName = w(476) // B = w(476),
obfuscatedFunctionName === n[9] && obfuscatedFunctionName === "QWRkcmVzcyI6IjB4MGM1REEwZjA3OTYyZGQwMjU2YzA3OTI0ODY" // => true
let base64CharactersOfParamsBase64 = btoa("" + prefixOfEncodedParams + obfuscatedFunctionName + suffixOfEncodedParams).split("") // I = (I = (I = (I = (I = btoa("" + W + B + S)).split(""))
let base64CharactersPlusOneOfParamsBase64 = base64CharactersOfParamsBase64.map(function(e) {
let charCodePlusOne = e.charCodeAt() + 1 // e[w(488)](0) + 1; w(488) === "charCodeAt"
return charCodePlusOne
}).map(function(e) { // w(482) === "map"
return String.fromCharCode(e)
}).join("")
Which is effectively the same as:
let base64CharactersPlusOneOfParamsBase64 = base64CharactersOfParamsBase64.map(e => String.fromCharCode(e.charCodeAt() + 1)).join("")
Example value and test
base64CharactersPlusOneOfParamsBase64 === '[YmLNHK6TU[Kblm4UXqKeF2FTYSSW2KsZ32XfnO6TU[KblJ1UVeONWKGSYebblF{U2S[fWqIVYeObmVzXYqCN1:VTUCQSGmOWHiWUWSGOl6VRU[OSFG2UVSCe2eqTYOKcYixZmetNFmrc4qOblG{TX25e2GYVnukcW[7Z4mKOlmrRkSOWGKFUmSsNF2rTYmOWFFzUXqofmqIVUKTSFVyUmeKOWqFRYe[WHtxUUKKOV6FSUGOflFzUnmKd1mucIWlS2[6[H2Hd1mrc3mOWG[1TXm4bWmuSoqbWYi4TXqwbV2J[4mPSHyrXlSCNV6FXUWPNmlxUWeSN11xXYiSWHe5Xn2Ge2KrWYmPfnyuXUKPcF1zUlePflKrTX5xQR>>' // => true
base64CharactersPlusOneOfParamsBase64 === I // => true
Now compare it with string in request:
https://poocoin.app/api2/candles-bsc?data=[YmLNHK6TU[Kblm4UXqKeF2FTYSSW2KsZ32XfnO6TU[KblJ1UVeONWKGSYebblF{U2S[fWqIVYeObmVzXYqCN1:VTUCQSGmOWHiWUWSGOl6VRU[OSFG2UVSCe2eqTYOKcYixZmetNFmrc4qOblG{TX25e2GYVnukcW[7Z4mKOlmrRkSOWGKFUmSsNF2rTYmOWFFzUXqofmqIVUKTSFVyUmeKOWqFRYe[WHtxUUKKOV6FSUGOflFzUnmKd1mucIWlS2[6[H2Hd1mrc3mOWG[1TXm4bWmuSoqbWYi4TXqwbV2J[4mPSHyrXlSCNV6FXUWPNmlxUWeSN11xXYiSWHe5Xn2Ge2KrWYmPfnyuXUKPcF1zUlePflKrTX5xQR%3E%3E
In the next part, we'll write the actual code that will construct the URL and retrieve the data.
Outro
If you have anything to share, any questions, suggestions, or something that isn't working correctly, feel free to reach out via Twitter at @ilyazub.
P.S. Thanks to @dmitryzub for help on this project and for co-authoring this article.
Top comments (0)