Generate Fingerprint
So, if you have visited the previous page containing Fingerprint object schema, you already know it's quite cumbersome.
Luckily, there is an easier way to do it.
We have implemented fingerprint generation logic into our tool - aemulari, which generates fingerprint just the same way as Surfinite App does it when you click Generate
button on a profile page. The command for this is generate-fp
. Here's the help message:
$ ./aemulari generate-fp --help
Generate fingerprint usage:
--os TEXT Operating System (required), allowed values: "windows",
"linux", "macos"
--os-version TEXT OS version (optional). For Windows: "7", "8", "8.1",
"10" and "11". For macOS: "11" (Big
Sur), "12" (Monterey) and "13" (Ventura). For Linux it must be kernel
version string like "5.15.0". Defaults: "10" for
Windows, "13" for macOS and "5.15.0" for Linux
--chrome-version TEXT Full Chrome version (optional, recommended), e.g.
"106.0.5249.134". Default: the newest version packed
with this version of aemulari. Might be outdated
--pretty Prettify JSON. Might be very handy for manual use when
testing
This command generates fingerprint object with the same logic as in Surfinite App and returns JSON as its output.
Try it yourself
Just hop into your terminal or CMD and try it yourself. You can use --pretty
flag to make the output readable.
You would then use it to create your profile. Or first set some custom fields (like change screen or disable WebGL) and then create profile. Here's a code example:
val process = ProcessBuilder(
listOf(
"/home/myuser/.surfinite/aemulari/aemulari",
"generate-fp",
"--os", "windows",
"--os-version", "10",
"--chrome-version", "106.0.5249.134"
)
)
.start()
val procOutput = process.inputStream.readAllBytes().decodeToString()
process.waitFor()
val exitCode = process.exitValue()
if (exitCode != 0) {
println("Generate Fingerprint error. Exit code: $exitCode.")
println(procOutput)
return
}
val fingerprintObject = Json.parseToJsonElement(procOutput)
val clusterId = "62aad24955d7cb159cae7fae"
val profileRequest: JsonObject = buildJsonObject {
put("parentId", clusterId)
put("name", "Test Profile")
put("fingerprint", fingerprintObject)
}
val client = HttpClient(CIO) {
install(ContentNegotiation) { json() }
}
val response = client
.post("$apiUrl/profiles?api_key=$apiKey") {
contentType(ContentType.Application.Json)
setBody(profileRequest)
}
.body<JsonObject>()
println("Profile ID: ${response["_id"]!!.jsonPrimitive}")
The command is completely offline, no requests are made to our servers. The only error you can come up with it, is if you pass an incorrect argument, e.g. --os=wind0ws
. The program would exit with code 1
in this case and an error message printed to stdout
.