Opt-In Software Blog

Software, dvelopment, and practical insights

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.

How to View the Secret Key in the Authenticator Chrome Extension

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

The Authenticator extension for Google Chrome is a convenient way to store and generate two-factor authentication (2FA) codes directly in your browser.

When adding an account, the extension provides several options:

  • Scan QR Code
  • Manual Entry
  • Import QR Images
  • Import OTP URLs

You can also edit an existing entry after it has been added. For example, you can change its Issuer or Username.

However, there is one thing you cannot do through the normal interface: view the secret key of an existing authenticator entry.

This can become a problem when you want to migrate your accounts to another authenticator application. The secret key is required to add the same TOTP authentication method to another app.

Fortunately, there is a way to retrieve it.

Export a backup

Open the Authenticator extension and go to:

Settings → Backup

Then click:

Download Backup File

The downloaded backup file contains the OTP configuration for your accounts.

Inside the file, you will find entries similar to this:

otpauth://totp/website.com:user?secret=YOUR_SECRET_KEY&issuer=website.com

The value of the secret parameter is the TOTP secret key:

secret=YOUR_SECRET_KEY

You can use this secret key to add the account to another authenticator application.

This method is especially useful when the original website does not provide an easy way to display or regenerate the existing TOTP secret.

Downloading a Specific Stable Google Chrome Version for Linux

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

Google only offers the latest build on its official download page. If you need a specific older or pinned stable version for testing, you can download the .deb package directly from Google’s servers.

1. Find the Chrome Version Number

You need the full release version string (e.g., 150.0.7871.181). You can find official build numbers using these resources:

2. Construct the Download URL

Google stores the package history in its Debian repository pool. Replace {CHROME_VERSION} in the template below with your target version number:

https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_{CHROME_VERSION}-1_amd64.deb

For example, to download version 150.0.7871.181, use the following URL:

https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_150.0.7871.181-1_amd64.deb

3. Download via Terminal

You can pull the package directly using wget or curl:

curl https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_150.0.7871.181-1_amd64.deb --output google-chrome-stable_150.0.7871.181-1_amd64.deb

Understanding SslMode and UpstreamSslMode in ProxyMapService

In the previous article, SSL/TLS Traffic Decryption in ProxyMapService, we looked at how ProxyMapService can decrypt SSL/TLS traffic by acting as a man-in-the-middle (MITM) proxy.

However, before traffic can be decrypted, ProxyMapService must first determine an important detail:

  • Is the client using TLS?
  • Does the upstream server expect TLS?

In many environments the answers are obvious, but not always. ProxyMapService provides two configuration options that allow you to control this behavior explicitly:

  • SslMode
  • UpstreamSslMode

Both settings support the same three values:

"No"
"Yes"
"Auto"

The default value for both settings is:

"Auto"

Where These Settings Can Be Configured

Like DecryptSSL, both settings can be configured either for a listener or for an individual host rule.

Listener Configuration

"Listen": {
    "Port": 5000,
    "RejectHttpProxy": false,
    "DecryptSSL": true,
    "SslMode": "Yes",
    "UpstreamSslMode": "No"
}

When configured on a listener, the settings apply to every connection received on that listening port (or port range).

This is useful when all traffic arriving on a particular port follows the same protocol.

Host Rule Configuration

The same settings can be configured for individual destinations.

Example:

"HostRules": {
    "Items": [
        {
            "Pattern": "^mysite\\.com$",
            "HostPort": 443,
            "DecryptSSL": true,
            "SslMode": "Yes",
            "UpstreamSslMode": "No"
        }
    ]
}

This rule applies only to connections matching both:

  • mysite.com
  • port 443

Connections to the same host on other ports are unaffected.

Instead of using a regular expression, you can specify a host name directly:

{
    "HostName": "mysite.com",
    "DecryptSSL": true,
    "SslMode": "Yes",
    "UpstreamSslMode": "No"
}

Since no port is specified, the rule applies to every port for that host.

Host rules override listener settings whenever a connection matches the rule, allowing different SSL behavior for different destinations.

Understanding SslMode

SslMode controls whether the incoming client connection is expected to use SSL/TLS.

The available values are:

No

The incoming connection is treated as plain TCP.

No TLS handshake is expected.

Yes

The incoming connection is always treated as TLS.

ProxyMapService immediately begins TLS negotiation with the client.

Auto

This is the default behavior.

Instead of relying on the listening port, ProxyMapService examines the first two bytes received from the client.

A TLS ClientHello always begins with:

0x16 0x03

If this signature is detected, the connection is treated as TLS.

Otherwise, it is processed as an unencrypted connection.

This automatic detection allows HTTP and HTTPS traffic to coexist on the same listener without requiring separate ports.

Understanding UpstreamSslMode

UpstreamSslMode controls how ProxyMapService connects to the destination server.

Unlike SslMode, which examines the client connection, this setting determines whether the outbound connection should be encrypted.

The available values are the same:

No

ProxyMapService always connects to the upstream server using plain TCP.

Yes

ProxyMapService always establishes a TLS connection to the upstream server.

Auto

This is the default behavior.

Instead of inspecting traffic, ProxyMapService determines whether TLS should be used based on the destination port.

The following ports are treated as secure by default:

  • 443 (HTTPS)
  • 465 (SMTPS)
  • 563 (NNTPS)
  • 636 (LDAPS)
  • 990 (FTPS)
  • 992 (Telnet over TLS)
  • 993 (IMAPS)
  • 995 (POP3S)
  • 3269 (Microsoft Global Catalog over SSL)
  • 8443 (Alternative HTTPS)

Connections to these ports are established using TLS.

Connections to other ports use plain TCP unless UpstreamSslMode is explicitly set to Yes.

When Should You Override Auto?

For most deployments, Auto is the recommended setting for both options.

However, explicit configuration is useful when working with non-standard environments.

Typical examples include:

  • HTTPS services running on custom ports.
  • Plain HTTP services listening on port 443.
  • Legacy applications that tunnel TLS over unexpected ports.
  • Environments where protocol detection must be disabled for compatibility or performance reasons.

In these situations, setting SslMode or UpstreamSslMode to Yes or No removes any ambiguity and ensures ProxyMapService uses the desired protocol.

Conclusion

SslMode and UpstreamSslMode give you precise control over how ProxyMapService handles encrypted connections.

SslMode determines whether the client connection is encrypted, while UpstreamSslMode determines whether the connection to the destination server should use TLS.

In most cases, the default Auto mode works without any additional configuration by automatically detecting TLS on incoming connections and using well-known secure ports for outbound connections.

When working with non-standard network topologies or custom protocols, these settings allow ProxyMapService to communicate correctly with both clients and upstream servers without requiring changes to the application itself.

Wattpad Text Selection and Copy Trick

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

If you ever need to copy text from Wattpad on desktop, here’s a method that still works for me.

  1. Open the story/chapter you want to copy from and wait until the page is fully loaded.

  2. Open the browser’s Developer Tools:

    • Chrome / Edge: press F12 or Ctrl + Shift + I
    • Firefox: press F12 or Ctrl + Shift + I
    • Safari: enable the Develop menu first, then choose Develop → Show JavaScript Console
  3. Go to the Console tab.

  4. Paste and run this command:

document.onselectstart = null;
  1. After that, you should be able to select text on the page normally.
  2. Highlight the text you want.
  3. In the Console, run:
console.log(window.getSelection().toString())
  1. The selected text will be printed in the console. You can then select it there and copy it to your clipboard with Ctrl+C.

A couple of notes:

  • Make sure the chapter has finished loading before you start.
  • If the selection doesn’t work immediately, refresh the page and try again.
  • This method was tested in a desktop browser using Developer Tools.

Hope this helps someone.

Accelerating Proxy Checks with Async Tasks Per Thread

One of the fastest ways to check large proxy lists in Web Proxy Checker is to use the Async Tasks Per Thread option.

Web Proxy Checker is a multi-threaded application. In the Check Threads setting, you can define how many worker threads will be used during proxy verification. A thread is an independent execution unit that can process tasks in parallel with other threads.

When Async Tasks Per Thread is enabled, each thread can handle multiple proxy checks simultaneously. Instead of waiting for one proxy request to finish before starting the next one, the thread launches several asynchronous tasks and processes many connections at the same time.

For example:

  • Check Threads: 20
  • Async Tasks Per Thread: 50

This means that up to 20 × 50 = 1,000 asynchronous proxy checks can run concurrently.

The result is a significant speed increase, especially when checking large proxy lists. In real-world usage, verifying a list of 2,000 proxies takes roughly 30 seconds, depending on proxy quality, target settings, and network conditions.

If you’re working with large proxy databases, enabling asynchronous tasks is one of the most effective ways to maximize checking performance.

Search