Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

User Agent Emulation

Rama emulates user agents at the HTTP and TLS layer:

HTTP and TLS Emulation

  1. HTTP Layer: Rama can emulate HTTP request headers, including User-Agent strings, Accept headers, and other browser-specific headers that websites use for fingerprinting.

  2. TLS Layer: The TLS handshake contains significant fingerprinting information. Rama can emulate specific TLS client configurations, including cipher suites, extensions, and other TLS parameters that browsers expose.

Rama does not emulate the JavaScript or Web API layer.

Technical Implementation

Rama implements user-agent emulation with profiles recorded from real browsers:

  • UserAgentProfile - One browser identity and the HTTP/1.1, HTTP/2, HTTP/3, TLS and QUIC observations recorded for it, per kind of request (navigation, form, fetch, XHR, WebSocket);
  • UserAgentDatabase - The profiles to choose from. Files in the older one-row-per-browser format are converted when loaded.

These profiles are applied to outgoing requests using middleware services:

Anything that cannot be reproduced exactly is replaced by Rama’s normal behaviour and listed in the request’s ProfilePreservationReport.

Rama includes a database of pre-configured profiles for common browsers and platforms, making it easy to emulate specific user-agents without manual configuration. These profiles are generated from real browser fingerprints collected through Rama’s fingerprinting service.

The emulation can be applied selectively based on the given input, allowing for sophisticated emulation strategies that can adapt to different scenarios or rotate between multiple profiles to avoid detection.

HTTP/3 profile budgets

Browsers advertise larger QPACK receive limits than Rama’s defaults; Chrome, for example, a 64 KiB dynamic table, 100 blocked streams and 256 KiB field sections. An emulated HTTP/3 connection raises its limits to the captured values, so it advertises exactly what the browser did. Each limit is memory the server may make the connection hold, so captured values are raised at most to Config::CAPTURED_QPACK_CEILING (a 256 KiB table, 256 blocked streams and 1 MiB field sections) and lowered to it beyond that. A client that does not emulate can ask for browser-sized limits with Config::default().with_browser_qpack_decoder_limits(). Observation remains disabled unless requested. Reserved SETTINGS entries are generated for each connection draw while their captured positions are retained.

Embedded Profile Data

Rama includes an ua-embed-profiles feature flag (embed-profiles on the standalone rama-ua crate) that, when enabled, embeds a collection of pre-configured user agent profiles directly into the binary. This eliminates the need for external profile files and ensures that Rama has immediate access to a variety of emulation profiles.

The embedded profiles are stored at rama-ua/src/profile/format/embed_profiles.bin: a precompiled, zstd-compressed profile set exported from Rama’s fingerprinting service with rama ua export --embed. It holds, per profile:

  • the browser and platform identity (User-Agent, client, version, platform and device)
  • counted HTTP/1.1, HTTP/2 and HTTP/3 header and settings observations per request flow
  • counted TLS ClientHellos over TCP and over QUIC
  • QUIC transport parameters and first-flight structure, where the browser used HTTP/3

The profiles are analyzed when they are exported, so loading them only decompresses and decodes the file, in well under a second. Refresh it with just update-embedded-profiles; rama ua compact profiles.json --output embed_profiles.bin compiles an archive of your own the same way. rama ua export --embed and rama ua compact accept --exclude-user-agent to leave out a profile that cannot emulate itself; the refresh recipe passes the exclusions listed in rama-fp/justfile.

To see which browsers, versions and protocols (H1, H2, H3, TLS over TCP, QUIC) your build embeds, run rama ua view --embedded; add --summary for a plain list. rama ua view FILE does the same for an exported archive or a compiled set, such as the embedded file of another Rama version.

Using this feature allows applications to immediately start with realistic browser emulation without any additional setup, making it ideal for applications that need to maintain a low profile or operate in environments where external files might be difficult to manage.

To enable it, add the ua-embed-profiles feature to rama, or embed-profiles when you depend on rama-ua directly.

Emulating a browser from the CLI

rama send --emulate uses the embedded profiles; --emulate=profiles.json uses an archive of your own (see Capturing your own profiles). The request’s User-Agent picks the browser, the protocol flag picks the profile’s H1, H2 or H3 data. The User-Agent does not have to be a real one: desktop firefox, chrome android, safari ios or Firefox/158 pick a matching profile and send that browser’s own User-Agent (rama ua parse 'desktop firefox' shows how a value is understood):

rama send --emulate --http3 -H 'User-Agent: desktop firefox' https://h3.fp.ramaproxy.org/report

--emulate-initiator navigate|form|fetch|xhr|ws picks the kind of request. Cookies and connection options such as Connection: keep-alive belong to your request: pass them with -H and Rama puts them where the browser did. The rama-cli README lists the remaining --emulate-* options. In code, the same is ProfileEmulateLayer on an HTTP client with a UserAgentDatabase; captured TLS replay needs the BoringSSL backend.

Verifying a fingerprint with Wireshark

Compare what Rama sends with a capture of the real browser. Record Rama’s traffic with its TLS secrets; Rama writes them to the file named by SSLKEYLOGFILE, for TLS over TCP and over QUIC:

# terminal 1: capture
dumpcap -i any -f 'host h3.fp.ramaproxy.org' -w rama.pcapng
# terminal 2: the emulated request
SSLKEYLOGFILE=keys.log rama send --emulate --http3 -H 'User-Agent: ...' https://h3.fp.ramaproxy.org/report

In Wireshark set Preferences -> Protocols -> TLS -> (Pre)-Master-Secret log filename to keys.log (or pass -o tls.keylog_file:keys.log to tshark) and open rama.pcapng. What to compare against the browser’s capture:

LayerWhereDisplay filter
TLS ClientHello (TCP and QUIC)first CRYPTO / handshake recordtls.handshake.type == 1
QUIC transport parametersquic_transport_parameters extension of that ClientHellotls.quic.parameter
QUIC first flightInitial packets: sizes, packet numbers, CRYPTO frame layoutquic.long.packet_type == 0
HTTP/3 SETTINGSclient control streamhttp3.frame_type == 4
HTTP/3 header orderHEADERS frames, decoded field nameshttp3.header.header.name
HTTP/2 SETTINGS and header orderhttp2.type == 4 / http2.header.name

For a browser capture you need its secrets too: Chrome and Firefox honour SSLKEYLOGFILE; Safari does not, so capture it against a server you run and log the server’s secrets instead: rama serve fp also honours SSLKEYLOGFILE. Visiting https://fp.ramaproxy.org/report (or your own fp service) with both the browser and Rama shows the same comparison as a report, without Wireshark.

examples/tests/browser_profile automates this: a real browser is captured against a local fp service, Rama replays the exported profile, and the two packet captures are compared field by field with tshark. just examples/tests/embedded-profiles --rama target/debug/rama --output DIR emulates every embedded profile against a local rama serve echo, which reports per request whether its JA4 (TLS, also over QUIC) and JA4H fingerprints match the ones recorded for that profile.

💡 At Plabayo, we support the principle that information wants to be free, provided it is pursued ethically and within the bounds of applicable law.

We do not endorse or support any malicious use of our technology. We advocate for the programmatic retrieval of publicly available data only when conducted responsibly — in a manner that is respectful, does not impose an undue burden on servers, and avoids causing disruption, harm, or degradation to third-party services.