feat(ja3): Update JA3 fingerprinting source and parsing

This commit is contained in:
2025-11-19 15:44:24 +11:00
parent 567048911d
commit 65b46e1975
3 changed files with 49 additions and 4 deletions

View File

@@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"regexp"
"strings" "strings"
"time" "time"
@@ -132,11 +133,20 @@ func (f *Flaresolverr) ListSessionsV1(sessionID string) (*V1ResponseBase, error)
} }
func (f *Flaresolverr) GetJa3AndUserAgent() (ua string, ja3 string, err error) { func (f *Flaresolverr) GetJa3AndUserAgent() (ua string, ja3 string, err error) {
resp, err := f.GetV1("https://tls.peet.ws/api/tls", nil) resp, err := f.GetV1("view-source:https://tools.scrapfly.io/api/tls", nil)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
return resp.Solution.UserAgent, resp.Solution.RawResponse.(map[string]any)["tls"].(map[string]any)["ja3"].(string), nil j := regexp.MustCompile(`{(.*)}`).FindStringSubmatch(resp.Solution.RawResponse.(string))
if len(j) < 2 {
return "", "", fmt.Errorf("failed to get ja3")
}
ja3Obj := Ja3{}
err = json.Unmarshal([]byte(j[0]), &ja3Obj)
if err != nil {
return "", "", err
}
return resp.Solution.UserAgent, ja3Obj.Ja3, nil
} }
func (f *Flaresolverr) preSimulateRequest(opts *SimulateOptions) error { func (f *Flaresolverr) preSimulateRequest(opts *SimulateOptions) error {

View File

@@ -83,3 +83,36 @@ type IndexResponse struct {
type HealthResponse struct { type HealthResponse struct {
Status string `json:"status"` Status string `json:"status"`
} }
type Ja3 struct {
Ja3 string `json:"ja3"`
Ja3N string `json:"ja3n"`
Ja3Digest string `json:"ja3_digest"`
Ja3NDigest string `json:"ja3n_digest"`
ScrapflyFp string `json:"scrapfly_fp"`
ScrapflyFpDigest string `json:"scrapfly_fp_digest"`
TLS struct {
Version string `json:"version"`
Ciphers []string `json:"ciphers"`
Curves []string `json:"curves"`
Extensions []string `json:"extensions"`
Points []string `json:"points"`
Protocols []string `json:"protocols"`
Versions []string `json:"versions"`
HandshakeDuration string `json:"handshake_duration"`
IsSessionResumption bool `json:"is_session_resumption"`
SessionTicketSupported bool `json:"session_ticket_supported"`
SupportSecureRenegotiation bool `json:"support_secure_renegotiation"`
SupportedTLSVersions []int `json:"supported_tls_versions"`
SupportedProtocols []string `json:"supported_protocols"`
SignatureAlgorithms []int `json:"signature_algorithms"`
PskKeyExchangeMode string `json:"psk_key_exchange_mode"`
CertCompressionAlgorithms string `json:"cert_compression_algorithms"`
EarlyData bool `json:"early_data"`
UsingPsk bool `json:"using_psk"`
SelectedProtocol string `json:"selected_protocol"`
SelectedCurveGroup int `json:"selected_curve_group"`
SelectedCipherSuite int `json:"selected_cipher_suite"`
KeyShares []int `json:"key_shares"`
} `json:"tls"`
}

View File

@@ -2,13 +2,14 @@ package test
import ( import (
"encoding/json" "encoding/json"
"fmt"
"testing" "testing"
"git.nite07.com/nite/go-flaresolverr" "git.nite07.com/nite/go-flaresolverr"
) )
func TestGetV1(t *testing.T) { func TestGetV1(t *testing.T) {
f, err := flaresolverr.GetInstance("http://127.0.0.1:8191", "", "") f, err := flaresolverr.GetInstance("http://100.64.0.1:8191", "", "")
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
@@ -27,7 +28,7 @@ func TestGetV1(t *testing.T) {
} }
func TestImitateGet(t *testing.T) { func TestImitateGet(t *testing.T) {
f, err := flaresolverr.GetInstance("http://127.0.0.1:8191", "", "") f, err := flaresolverr.GetInstance("http://100.64.0.1:8191", "", "")
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
@@ -49,6 +50,7 @@ func TestImitateGet(t *testing.T) {
return return
} }
if resp1.Status != 200 { if resp1.Status != 200 {
fmt.Printf("status is not 200: %v", resp1.Status)
t.FailNow() t.FailNow()
} }
jsonBytes, _ := json.Marshal(resp1) jsonBytes, _ := json.Marshal(resp1)