App

Monocle Assessment

Monocle can be used exclusively as a passive means of gathering statistics about your users' connections, requiring no backend integration.

In addition, you can also choose to implement real-time actions based on the contents of the Monocle Assessment on your backend. Here are a couple of scenarios:

  • Blocking risky form submissions from anonymizing VPNs
  • Logging the anonymizing status of newly created accounts
  • Reducing user friction for known-good Zero Trust networks like ZScaler and Netskope
  • Flagging in your database logins and account creation from residential proxies

By default, the Monocle Assessment appends itself as a hidden field (named monocle) to any <form> elements present on the page with a class of monocle-enriched.

For example:

<form class="monocle-enriched" action="/submit" method="POST">
<input type="text" name="email" />
<input type="password" name="password" />
<button type="submit">Submit</button>
</form>

This allows the backend server to log and/or take action using the Monocle Assessment.

Because the Monocle Assessment is encrypted (to prevent viewing and tampering by the client), it must first be decrypted in one of two ways:

  1. Using your Monocle Secret Key to authenticate with the Monocle Decryption API.
  2. Using your Monocle Private Key to decrypt the Monocle Assessment directly on the backend.

Either method will provide you with the decrypted Monocle Assessment, whose schema is outlined in the section below.

The Monocle Assessment object

Attributes
vpnboolean

Flag indicating whether or not this connection was detected to be originating from a VPN

proxiedboolean

Flag indicating whether or not this connection was detected to be originating from a proxy of any type (datacenter or residential)

anonboolean

Flag indicating whether or not this connection was detected to be originating from IP space known to host anonymizing infrastructure - this is a modifier to vpn and proxied and will never be true by itself

rdpboolean

Flag indicating whether or not this connection was detected to be originating from a remote desktop service

dchboolean

Flag indicating whether or not this connection was detected to be originating from a datacenter

ccstring

Country code of the source IP address (ISO 3166 ALPHA-2)

ipstring

Source IPv4 address as seen by Monocle

ipv6optional string

Source IPv6 address as seen by Monocle

tsstring

ISO 8601 datetime format of the Monocle Assessment generation

completeboolean

Flag indicating if the Monocle process completed fully; a false value is indicative of a higher chance of false positives/negatives

idstring

Unique Monocle-generated ID identifying the generated Monocle Assessment

sidstring

The name of your Monocle Application

servicestring

If Monocle is able to identify the service in use, it will be labeled here. This value corresponds to the service tags found here. This field is only exposed to Enterprise Monocle users.

cpdoptional string

Customer-provided data originally passed into the Monocle load. Truncated after 1024 characters.

THE MONOCLE ASSESSMENT OBJECT
{
"vpn": true,
"proxied": false,
"anon": true,
"rdp": false,
"dch": false,
"cc": "US",
"ip": "198.51.23.210",
"ipv6": "2001:db8:e214:9f67:711:f03e:a141:3871",
"ts": "2022-10-17T14:03:19-04:00",
"complete": true,
"id": "580f12c9-8030-4d49-b39f-35dfe560fa9e",
"sid": "example-sign-up-form",
"service": "MULLVAD_VPN",
"cpd": "test-cpd-value"
}

Monocle Assessment Verification

Because Monocle is stateless, verifying the veracity of an incoming Monocle Assessment is the responsibility of the integrating user.

The client cannot modify the decrypted contents of the Monocle Assessment, but they could tamper with it (thereby breaking its ability to be decrypted) or replay it in subsequent requests.

Spur recommends the following methods for validating a Monocle Assessment:

  • Verify that the Monocle Assessment is included (if tied to a form submission).
  • Verify that the Monocle Assessment successfully decrypts, indicating it has not been modified.
  • Verify that ip matches the IP address of the form submission request (note: see the below section for caveats of this approach).
  • Verify that ts is within an acceptable range of the current datetime. We suggest ~5 minutes or a time frame commensurate with your use case.
  • Check the value of complete. Under normal operation, this will be true. A false value indicates Monocle was unable to complete its evaluation, suggesting a higher possibility of false positives or negatives.

IP Verification Caveats

Apart from replayed Assessments, there are several instances where the IP you might see in an Assessment may not exactly match the IP your backend sees.

Multiple Egress IPs Within the Same Network

In some cases, a single logical network (such as a large WiFi deployment or carrier-grade NAT environment) may route traffic through multiple egress IP addresses. These IPs often fall within the same subnet. When strict validation is applied—requiring an exact match between the request IP and the assessment IP—this can result in unnecessary false failures. Recommended handling: Instead of requiring an exact IP match, validate that the assessment IP belongs to the same subnet (e.g., /24 or /23, configurable) as the request IP. This relaxed validation still ensures network consistency while accounting for multi-egress network architectures.

Split-Tunnel or ZTNA/Routing Discrepancies Across Managed Networks

In more complex network environments—such as corporate, educational, or otherwise managed networks—traffic may be routed through different providers or appliances depending on the destination. For example, a Zero Trust Network Access (ZTNA) or similar appliance may selectively proxy outbound requests. This can result in the request originating from a completely different network or autonomous system than the assessment IP, even though the user is on a single device behind a managed gateway. Recommended handling: These scenarios often cannot be resolved through subnet-based validation. The typical solution is to prompt the user to retry the action from a different network or ensure no split-tunnel/ZTNA routing rules are interfering.

Customer-provided data

Optionally, in the event you wish to attach a custom session ID, nonce, CSRF token, etc., you may provide an arbitrary string (limited to 1024 characters) during the initial Monocle script load.

The value for this additional URL parameter called cpd (customer-provided data) will be present in a field of the same name in the resulting Monocle Assessment.

You can use the cpd parameter to add an arbiratary, session-based tag to the Monocle Assessment. This can in turn be used for custom session verification, tracking, and analysis on your backend.

Example implementation:

<script
async
src="https://mcl.spur.us/d/mcl.js?tk=<your monocle token>&cpd=test-cpd-value"
id="_mcl"
></script>

As with the interpretation of the Monocle Assessment, how you handle verification errors depends on your use case. This could range from accepting the form submission anyway, returning a validation error requiring the user to retry the form, logging the event in a backend database, or rejecting the form submission outright.

Common Scenarios

The primary value of Monocle is delivered in the first three fields: vpn, proxied, and anon.

In the matrix below, we've provided a few possible scenarios covering different combinations of values for these flags.

Note

The anon flag will never be true unless either vpn or proxied is also true.

Possible Interpretationanonvpnproxied
- Proxy through a VPN
- VPN service that uses proxies
XXX
- Residential Proxy
- Datacenter Proxy
XX
- Commercial VPN serviceXX
- Non-anonymizing/corporate VPNX
- Non-anonymizing/corporate proxyX
- No proxy or VPN detected