buildBrowserHeaders function

Map<String, String> buildBrowserHeaders(
  1. UserAgentDevice type, {
  2. Map<String, String> explicit = const {},
  3. String? overrideUserAgent,
})

Builds a coherent set of request headers for type (a browser fingerprint) and overlays caller-supplied explicit headers on top so they always win.

If the caller forces a User-Agent — via overrideUserAgent or a User-Agent key in explicit — the generated Sec-CH-UA* client hints are dropped, since they would no longer match that UA and a mismatch is itself a detection signal.

Implementation

Map<String, String> buildBrowserHeaders(
  UserAgentDevice type, {
  Map<String, String> explicit = const {},
  String? overrideUserAgent,
}) {
  final profile = randomBrowserProfile(type);
  final bool hasExplicitUA =
      explicit.keys.any((k) => k.toLowerCase() == 'user-agent');
  final bool customUA = overrideUserAgent != null || hasExplicitUA;

  final headers = <String, String>{...profile.headers};
  if (customUA) {
    headers.removeWhere((k, _) => k.toLowerCase().startsWith('sec-ch-ua'));
  }
  headers['User-Agent'] = profile.userAgent;

  // Caller-supplied headers take precedence.
  headers.addAll(explicit);

  // An explicit override wins over everything, including a UA in [explicit].
  if (overrideUserAgent != null) {
    headers['User-Agent'] = overrideUserAgent;
  }

  return headers;
}