Opt-In Software Blog

Software, dvelopment, and practical insights

How to Quickly Get the Direct URL from a Tracking Link

Read in: English | Русский

Services, online stores, and other websites often use tracking links instead of direct links.

This is especially noticeable in emails: a link to a question, order, product, or another page first goes through an intermediate service that tracks the click and then redirects you to the actual URL.

But tracking links are not limited to email. You can also encounter them on forums, in comments, communities, and other services — basically anywhere the site owner wants to track clicks on external links.

Sometimes the actual URL is already embedded directly in one of the tracking link’s parameters. For example:

https://tracking.example.com/click?u=https%3A%2F%2Fexample.com%2Forders%2F12345&campaign=email

Here, the u parameter contains the destination URL:

https%3A%2F%2Fexample.com%2Forders%2F12345

You don’t have to copy and decode it manually. You can quickly extract the direct URL right in DevTools.

How to do it

  1. Copy the tracking link.
  2. Open DevTools by pressing F12.
  3. Go to the Console tab.
  4. Enter:
const url = new URL("https://tracking.example.com/click?u=https%3A%2F%2Fexample.com%2Forders%2F12345&campaign=email");
  1. Then retrieve the value of the parameter:
url.searchParams.get("u");

The Console will display the already decoded direct URL:

https://example.com/orders/12345

You can even click the link directly in the Console.

The URL object provides access to query parameters through searchParams, and URLSearchParams.get() returns the value of a specific parameter. Query parameter values are decoded automatically, so there is no need to call decodeURIComponent() separately.

Of course, the parameter name will not always be u. Depending on the service, it could be url, target, redirect, redirect_url, or something else.

The main thing is to inspect the tracking link and look for a parameter that contains the encoded destination URL.

It’s a simple way to get the direct link without opening the tracking URL and going through the intermediate service.

Tools for Digital Footprint Auditing

Read in: English | Русский

Tools for Digital Footprint Auditing

Modern anti-fraud systems (Akamai, Cloudflare, PerimeterX) have long moved past analyzing just IPs and Cookies. Today, identification relies on Browser Fingerprinting — evaluating canvas/WebGL rendering artifacts, audio subsystem entropy, JA3/JA4 network stack hashes, and JS prototype behaviors. 

Top 9 Browser Fingerprint Checkers

  • BrowserScan — A comprehensive scanner tracking over 50 parameters. It detects automation frameworks (Puppeteer/Selenium) and scores overall profile consistency (Human Score).
  • BrowserLeaks — The go-to tool for low-level analysis. It verifies JA3/JA4 TLS fingerprints, HTTP/2 characteristics, and provides raw Canvas/WebGL hashes.
  • CreepJS — An open-source checker designed to expose spoofing. It analyzes Prototype Pollution, hidden anomalies in JS objects, and calculates a baseline Trust Score.
  • Pixelscan — A tool focused on logical data consistency. It cross-references environment metrics like system language, browser timezone, and proxy geolocation to catch mismatches.
  • Iphey — A simulator modeled after fintech and ad-tech verification engines. It evaluates profiles based on Autonomous System (ASN) reputation and hardware parity.
  • Cover Your Tracks (EFF) — A project by the Electronic Frontier Foundation. It measures browser uniqueness in bits of entropy against a live database of real users.
  • AmIUnique — A statistics-driven utility. It displays the exact percentage of global users sharing your specific font lists or screen resolution.
  • Scrapfly Browser Fingerprint Test — A verification tool developed by a web scraping platform. It simulates popular bot-detection challenges and monitors runtime reactions to script injections.
  • Whoer.net — A quick network perimeter assessment tool. It identifies WebRTC IP leaks, references DNSBL blocklists, and detects potential proxy/VPN tunnels using MTU analysis.

Comparative Analysis

Tool Focus JS / API Analysis Depth Network Stack Inspection Key Metric / Feature
BrowserScan Full profile auditing High Medium Automated consistency scoring
BrowserLeaks Low-level APIs High High (JA3/JA4) Aspect-by-aspect vector testing
CreepJS Spoof & mask detection Extreme Minimum In-depth JS prototype tracking
Pixelscan Profile data integrity Medium Medium System vs. IP anomaly detection
Iphey Reputation scoring Medium High (ASN, Proxy) ASN trust and behavior validation
Cover Your Tracks Privacy & tracking defense Medium Minimum Entropy measurements in bits
AmIUnique Global metadata trends Medium Minimum Percentage comparison with real devices
Scrapfly Test Anti-bot mitigation High High (HTTP/2) Cloudflare / Akamai engine simulation
Whoer.net Network perimeter Basic High (MTU, DNSBL) Rapid real IP exposure testing

WebSocket Session API in ProxyMapService

Read in: English | Русский

Real-Time Traffic Monitoring: Implementing a WebSocket Subscription API in ProxyMapService

Web scraping applications frequently require real-time tracking of all currently downloading URLs.

However, achieving this in practice is far from trivial. For instance, if the target application is a web browser, capturing network activity typically requires globally overriding the built-in fetch and XHR (XMLHttpRequest) methods. The situation becomes significantly more complex if the web page contains iframe elements: you must dynamically inject fetch and XHR overrides into them as well, adding a heavy layer of complexity and fragility to the system. Custom injection scripts can easily conflict with Content Security Policies (CSP) or simply miss requests originating from isolated contexts. 

Instead of breaking frontend logic inside the browser and relying on complex script injections, a much more reliable approach is to leverage the proxy layer. To achieve this, an optional WebSocket Session API was implemented in ProxyMapService. It allows external applications to connect directly to the proxy, supply a URL filter, and instantly receive push notifications for all requested resources. 

Configuration and Connection Logistics

The entire mechanism is managed by the SessionAPI section in the appsettings.json configuration file. Here is how it looks by default: 

"SessionAPI": {
    "Enabled": false,
    "WebSocketsEnabled": false,
    "Domain": ""
}

As you can see, by default, the entire SessionAPI infrastructure, including WebSockets, is turned off, and the Domain property is left empty. 

Option 1. Working via Local Port (Empty Domain)

When Domain is empty, the control endpoints are accessed like a regular web server on one of the ports that ProxyMapService listens to for incoming connections. For example, if the proxy is running on port 5000: 

To fully isolate control traffic from proxied traffic, it is recommended to enable the API and define a special internal domain: 

"SessionAPI": {
    "Enabled": true,
    "WebSocketsEnabled": true,
    "Domain": "proxymapper"
}

In this mode, proxymapper acts as a dedicated system domain. When ProxyMapService detects that a client is trying to access the proxymapper host, it intercepts the request locally and handles it as a call to the SessionAPI instead of routing it out to the external network. 

Crucial Nuance for Command-Line Utilities (e.g., cURL):

If you are using curl to route traffic through the proxy, the socks4 protocol will not allow you to call the internal API at all. Furthermore, the socks5:// prefix must be replaced with socks5h:// (e.g., socks5h://127.0.0.1:5000). This ensures that curl does not attempt to resolve the proxymapper domain locally via your OS DNS, but instead delegates the name resolution directly to the proxy server itself. 

With this configuration, the WebSocket Session API endpoint will be accessible via: ws://proxymapper/session/ws

How It Works in Practice

Using the subscription mechanism is straightforward for a developer: 

  1. Establishing a Connection: The client opens a persistent WebSocket connection to ws://proxymapper/session/ws.
  2. Sending a Filter: Immediately after a successful connection, the client sends a text JSON message containing a subscribe action and a regular expression (Regex) matching the target URLs:

 

{
  "action": "subscribe",
  "pattern": "api\\.example\\.com/v1/.*"
}
  1. Subscription Confirmation and session_id: The server replies with a confirmation message acknowledging the registered filter, which includes vital execution context:

 

{
  "status": "subscribed",
  "session_id": ":5000"
}

What does session_id mean and how does traffic isolation work? 

  • session_id represents a unique session identifier. If your environment utilizes authentication via a Sticky Proxy, this string identifier is explicitly bound to the user upon authentication.
  • If a Sticky Proxy is not used, the session_id returns a colon followed by the incoming port number (e.g., :5000). This means that notifications are strictly isolated to the specific port through which the subscription was created.
  • Lifecycle Rule: The user is guaranteed to receive notifications for URLs downloaded strictly within the session that was active at the moment of subscription. If the proxy session changes, notifications for the old subscription will cease. Similarly, under port-based isolation (without sticky routing), you will never see traffic passing through another proxy port inside the WebSocket channel for port :5000.
  1. Receiving Notifications: When a downloaded URL matches your pattern, the proxy server dispatches a flat, structured event optimized for fast reading:

 

{
  "event_type": "url_matched",
  "timestamp": "2026-09-02T10:20:45.0328755Z",
  "session_id": ":5000",
  "method": "GET",
  "url": "https://api.example.com/v1/users/profile"
}

Testing Environment: Proxy WebSocket Control Panel

The test web panel is hosted in a dedicated project subdirectory: tests\test-websocket

Inside the folder lies a self-contained HTML file, index.html, which implements the diagnostic interface: 

<!-- Located at: \tests\test-websocket\index.html -->
<div class="card">
    <h2>Proxy WebSocket Control Panel</h2>
    <div class="form-group">
        <input type="text" id="wsUrl" value="ws://proxymapper/session/ws">
        <button onclick="toggleConnection()">Connect</button>
    </div>
    <div class="form-group">
        <input type="text" id="filterPattern" value="(google\.com|yandex\.ru)/.*">
        <button onclick="sendSubscription()">Set Filter</button>
    </div>
</div>

How to Run the Test and Verify Monitoring:

  1. Launch the configured ProxyMapService with WebSockets enabled and the domain set to proxymapper.
  2. Open the tests\test-websocket\index.html file in any modern browser whose traffic is being routed through your proxy.
  3. Click the Connect button, set your regex filter pattern, and watch live notifications populate the dark console UI with full request details instantly.

Conclusion

Shifting URL tracing logic out of fragile browser scripts and into the ProxyMapService layer provides 100% visibility into network requests. It no longer matters where a request originates—be it the main window, a heavy background iframe, or a hidden service worker—the proxy server reliably intercepts, filters based on the active session (or port), and safely delivers the event to the client via a WebSocket subscription without modifying a single line of original page code.

Kinescope JSON LD Extractor

Read in: English | Русский

How I Built a Browser Extension to Download Videos from Kinescope for Offline Learning

I travel a lot — trains, planes, long drives out of town. And I always want to use that time productively: read, listen to podcasts, or learn something new.

The problem is, internet connectivity on the road is rarely reliable. And many educational platforms use the Kinescope player, which doesn’t offer a built-in way to download videos for offline viewing.

Sure, you could open DevTools, find the .m3u8 playlist in the network requests, copy the link, fire up FFmpeg in the terminal… But doing that every single time — especially when there are dozens of videos — is tedious and eats into time better spent actually learning.

I wanted a simple solution: open the video page, click a button, and have everything ready for offline watching.


Why a Browser Extension?

I considered a few options: writing a parser script, using a download manager, or building a browser extension.

I went with an extension because it’s the most natural and convenient approach:

  • It works right on the video page — no context switching.
  • It can intercept the player’s network requests in real time.
  • Everything is controlled with a single button. No extra steps.

The workflow is dead simple: open the lecture, click “Save,” move on to the next one. Repeat for all the materials I plan to watch on the road.


What I Built

The extension does two things:

  1. Intercepts all links to video and audio streams requested by the Kinescope player.
  2. Saves them to Downloads/kinescope/[Video_Title]/ along with metadata (title, duration, description).

A floating button appears on the page showing how many streams have been found. One click — and all the links are saved to your folder, neatly sorted by video and audio.

After that, I run a Python script that automatically stitches everything together using FFmpeg into a ready-to-watch .mp4 file. And just like that — a library of lectures ready for offline viewing.


The Result

Now preparing for a trip takes just a few minutes:

  1. Open all the videos I need → click the button on each page.
  2. Run one script → it processes everything automatically.
  3. Copy the finished files to my laptop or tablet and hit the road.

No DevTools, no manual copying of links. Just time well spent.


The extension is open source and can be installed manually via developer mode in Chrome. All you need are four files from the repository:

👉 Kinescope JSON-LD Extractor PRO on GitHub 👈

Hope you find it useful.

How to Download a Specific ChromeDriver Version

Read in: English | Русский

Sometimes you need a specific version of ChromeDriver rather than the latest one — for example, to match a particular version of Google Chrome.

For this, you can use Chrome for Testing, a Chrome flavor specifically designed for web testing and automation.

The project provides a JSON file containing available versions and download links:

known-good-versions-with-downloads.json

For example, let’s say you need ChromeDriver version 151.0.7922.138. The JSON contains an entry for this version with download URLs for different platforms:

{
  "version": "151.0.7922.138",
  "revision": "1654411",
  "downloads": {
    "chromedriver": [
      {
        "platform": "linux64",
        "url": "https://storage.googleapis.com/chrome-for-testing-public/151.0.7922.138/linux64/chromedriver-linux64.zip"
      },
      {
        "platform": "win64",
        "url": "https://storage.googleapis.com/chrome-for-testing-public/151.0.7922.138/win64/chromedriver-win64.zip"
      }
    ]
  }
}

The downloads.chromedriver section contains download links for different platforms: linux64, mac-arm64, mac-x64, win32, and win64.

Finding the URL using Chrome DevTools

The JSON file is quite large, but you don’t need to browse it manually. You can use Chrome DevTools to find the exact download URL.

Open the JSON file in Chrome, press F12, switch to the Console tab, and run:

JSON.parse(document.body.innerText).versions
  .find(x => x.version === '151.0.7922.138')
  ?.downloads.chromedriver
  .find(x => x.platform === 'win64')
  ?.url

The console will return the direct download URL:

https://storage.googleapis.com/chrome-for-testing-public/151.0.7922.138/win64/chromedriver-win64.zip

Simply change the version and platform in the command to get the ChromeDriver you need.

This approach requires no additional software or online JSON tools — everything can be done directly in Chrome DevTools.

Search