Opt-In Software Blog

Session API for Sticky Proxy Management in ProxyMapService

In a previous article, Making Any Scraper Work with Sticky Proxies, we discussed how ProxyMapService maps local ports to independent sticky proxy sessions.

Each local port automatically receives its own session ID and keeps it for the configured StickyProxyLifetime. This allows applications that only support simple IP:PORT proxies to work with modern session-based proxy providers.

Until now, session management in ProxyMapService was completely automatic. While this works well for many use cases, some applications need direct control over when sessions are created, rotated, or discarded.

The latest version of ProxyMapService introduces a Session API that allows applications and scripts to inspect, reset, and create sessions on demand.

How sessions work

Assume the following configuration:

{
  "Listen": {
    "PortRange": {
      "Start": 10201,
      "End": 10300
    },
    "StickyProxyLifetime": 10
  }
}

When traffic is sent through port 10201, ProxyMapService generates a session ID:

10201 → session LZpmRqdu

All requests made through this port will use the same sticky session until it expires.

The new Session API exposes this information and allows manual control over the session lifecycle.

Enabling Session API

For security and compatibility reasons, Session API is disabled by default.

To enable it, add the following section to your appsettings.json:

{
  "SessionAPI": {
    "Enabled": true,
    "Domain": "portmapper"
  }
}

Configuration Options

Option Description
Enabled Enables Session API endpoints.
Domain Virtual domain used to access Session API endpoints through a mapped proxy port.

With the configuration above, Session API can be accessed using requests such as:

curl -x http://127.0.0.1:10201 http://portmapper/session/

Using an Empty Domain

The Domain setting is optional and may be set to an empty string:

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

When Domain is empty, Session API endpoints become available directly on the mapped proxy port.

For example:

curl http://127.0.0.1:10201/session/

This can be convenient when working with local tools or scripts that do not support custom hostnames.

Get Current Session

Returns information about the session currently assigned to a port.

Example:

curl -x http://127.0.0.1:10201 http://portmapper/session/

Response:

{
  "session_id": "LZpmRqdu",
  "expires_at": "Wed, 10 Jun 2026 16:09:43 GMT",
  "expired": false
}

If the session is still active, repeated calls return the same information.

When the sticky session expires, ProxyMapService automatically generates a new session ID and the endpoint will return the new session details.

This can be useful for monitoring session state or checking how much time remains before rotation.

Reset Current Session

Sometimes you want to force a session change without waiting for the expiration timer.

The /session/reset endpoint removes the current session associated with the port.

Example:

curl -x http://127.0.0.1:10201 http://portmapper/session/reset

Response:

{
  "success": true
}

After the reset, the next request through port 10201 will automatically create a new session.

Typical use cases:

  • detected or blocked IP address
  • captcha escalation
  • failed scraping workflow
  • manual IP rotation

Create a New Session Immediately

The /session/new endpoint creates a new session immediately and assigns it to the port.

Example:

curl -x http://127.0.0.1:10201 http://portmapper/session/new

Response:

{
  "session_id": "uawxmttg",
  "expires_at": "Wed, 10 Jun 2026 16:19:48 GMT",
  "expired": false
}

Unlike /session/reset, which simply removes the current session, /session/new generates and activates a replacement session instantly.

This is useful when an application wants to rotate identities proactively while continuing to use the same local proxy port.

Why Not Just Change Ports?

A common question is why you would need a Session API if every port already has its own sticky session.

In practice, many scraping and automation systems assign a specific role to each local proxy port. For example:

127.0.0.1:10201 → Worker A
127.0.0.1:10202 → Worker B
127.0.0.1:10203 → Worker C

Workers may maintain their own queues, browser profiles, cookies, account assignments, or internal state tied to a particular proxy endpoint.

Changing ports is not always practical because it may require updating application configuration, restarting workers, or reassigning tasks.

With Session API, the application can keep using the same local proxy port while rotating the underlying sticky session whenever necessary.

Practical Examples

Session API can be useful when:

  • a target website starts returning captchas
  • an IP address becomes blocked or rate-limited
  • a scraping task needs a fresh identity immediately
  • monitoring systems need visibility into session expiration
  • applications want explicit control over session rotation timing

All of this can be done without restarting ProxyMapService and without changing the local proxy endpoint used by the application.

Summary

ProxyMapService was originally designed to make sticky proxies available to software that only understands simple IP:PORT proxy lists.

The new Session API adds direct control over the sticky sessions behind each mapped port.

Available endpoints:

  • GET /session/ — get information about the current session
  • GET /session/reset — remove the current session
  • GET /session/new — create and activate a new session immediately

This makes it easier to build scraping, automation, and data collection systems that need predictable control over proxy identities while continuing to use ordinary local proxy ports.

Using ProxyMapService to Fix pip Behind SOCKS5 Proxy

I ran into an issue where pip wasn’t working due to network restrictions. At the same time, I had access to a SOCKS5 proxy at:

192.168.1.100:1080

The problem was that pip doesn’t support SOCKS proxies out of the box. Normally, you’d install PySocks to enable that — but since pip itself wasn’t working, that wasn’t an option.

I used the ProxyMapService to expose the SOCKS5 proxy as a local HTTP proxy. Here’s the rule I configured:

{
  "Listen": {
    "Port": 10000,
    "RejectHttpProxy": false
  },
  "Authentication": {
    "Required": false,
    "Verify": false,
    "SetAuthentication": false
  },
  "ProxyServers": {
    "Items": [
      {
        "Host": "192.168.1.100",
        "Port": 1080,
        "ProxyType": "Socks5"
      }
    ]
  }
}

After that, pip started working by pointing it to the local HTTP proxy:

pip install cython --proxy http://127.0.0.1:10000
Collecting cython
  Using cached cython-3.2.4-cp311-cp311-win_amd64.whl.metadata (7.7 kB)
Using cached cython-3.2.4-cp311-cp311-win_amd64.whl (2.8 MB)
Installing collected packages: cython
Successfully installed cython-3.2.4

🎉

Making Any Scraper Work with Sticky Proxies

How to Use Sticky Proxies in Applications That Don’t Support Them

Many modern proxy providers sell so-called sticky proxies (also known as session-based proxies). This is a very popular solution for scraping, automation, data collection, and working around anti-bot protections.

What is a sticky proxy?

A sticky proxy is a proxy server that “locks” one IP address to you for a certain amount of time (for example, 5 or 10 minutes) using a session. Usually, the session is defined via the username, for example:

user-session-ABC123-sessTime-10:password@proxy_host:proxy_port

While the session is active, you will access the internet from the same IP address. When the time expires or you change the session ID, you get a new IP.

Today, most large proxy providers (residential, mobile, ISP) work exactly this way: you connect to a single host and port, and IP rotation is controlled via parameters in the username.

The problem: not all software supports sticky proxies

Many applications (scraping software, old parsers, bots, automation tools):

  • ❌ cannot work with proxies that require authentication
  • ❌ cannot manage sessions
  • ❌ expect just a list of IP:PORT, without username and password

Because of this, they cannot be directly connected to modern sticky proxy providers.

The solution: map local TCP ports through sticky proxies

The idea is very simple:

  • We run a local service
  • It opens a range of local ports
  • Each local port:
    • automatically connects to the sticky proxy
    • uses its own separate session
  • As a result:
    • 127.0.0.1:5001 → sticky proxy session AAA1
    • 127.0.0.1:5002 → sticky proxy session AAA2
    • 127.0.0.1:5003 → sticky proxy session AAA3
    • and so on

And your software just works with regular proxies without authentication:

127.0.0.1:5001
127.0.0.1:5002
127.0.0.1:5003

Ready-made solution: ProxyMapService

For this purpose, the following open-source project works perfectly:

👉 ProxyMapService
https://github.com/optinsoft/ProxyMapService

It can:

  • map port ranges
  • automatically manage sticky sessions
  • work with HTTP / SOCKS proxies
  • modify / generate username parameters

Configuration example

Here is an example config:

"ProxyMappings": [
  {
    "Listen": {
      "PortRange": {
        "Start": 10001,
        "End": 10100
      },
      "RejectHttpProxy": false,
      "StickyProxyLifetime": 10
    },
    "Authentication": {
      "Required": false,
      "Verify": false,
      "SetAuthentication": false,
      "RemoveAuthentication": false
    },
    "ProxyServers": {
      "Items": [
        {
          "Host": "PROXY_IP",
          "Port": PROXY_PORT,
          "ProxyType": "Http",
          "Username": "USERNAME",
          "Password": "PASSWORD",
          "UsernameParameters": [
            {
              "Name": "zone",
              "Value": "custom"
            },
            {
              "Name": "region",
              "Value": "US"
            },
            {
              "Name": "session",
              "Value": "^[A-Za-z]{8}",
              "SessionId": true
            },
            {
              "Name": "sessTime",
              "Value": "$sessTime",
              "Default": "10",
              "SessionTime": true
            }
          ]
        }
      ]
    }
  }
]

⚠️ In this example you need to replace:

  • PROXY_IP
  • PROXY_PORT
  • USERNAME
  • PASSWORD

with the values provided by your proxy provider.

How does it work in practice?

  • ProxyMapService opens local ports 10001–10100

  • Each port:

    • automatically generates a new sticky session
    • keeps it for StickyProxyLifetime = 10 minutes
  • You just set in your software:

127.0.0.1:10001
127.0.0.1:10002
127.0.0.1:10003
...

Conclusion

If your software:

  • doesn’t support proxy authentication
  • doesn’t support sessions
  • only works with IP:PORT lists

➡️ ProxyMapService solves this problem completely, allowing you to use modern sticky proxies without modifying your software.

Useful for:

  • scraping software
  • bots
  • automation tools
  • legacy tools
  • and basically any software with poor proxy support

ProxyMapService: ParseUsernameParameters

We’re excited to announce a new, optional feature in the ProxyMapService application. This feature enhances the flexibility of the authentication process by allowing you to simplify username validation.

The Challenge: Managing Complex Usernames

Sometimes, proxy usernames need to encode more information than just the account identifier.

For example, a proxy might look like this:

http://user-zone-custom-region-US-session-1234567-sessionTime-5:1111@127.0.0.1:8888

Username part of the proxy is user-zone-custom-region-US-session-1234567-sessionTime-5.

While this format might be necessary for other parts of the system or for identification, it complicates the standard authentication process by requiring the system to ignore the extra parts (zone, region, session, etc.) and focus solely on the actual username.

The Solution: Introducing ParseUsernameParameters

To address this need for cleaner authentication, we’ve introduced a new configuration parameter called ParseUsernameParameters. This boolean parameter resides within the Authentication section of the appsettings.json file.

  • Parameter Name: ParseUsernameParameters
  • Allowed Values: true or false (default is false)

What Does This Parameter Do?

When set to true, the ProxyMapService will parse the username string during authentication. It splits the username using the hyphen (-) delimiter. Crucially, only the first segment (the part before the first hyphen) is used for the authentication check. The remaining segments are ignored.

How It Works (Example)

Let’s take a look at the authentication logic with ParseUsernameParameters=true:

  1. Input Username (part of the proxy):

    "user-zone-custom-region-US-session-1234567-sessionTime-5"
  2. Authentication Logic (with ParseUsernameParameters=true):

    • The username string user-zone-custom-region-US-session-1234567-sessionTime-5 is split using the - character.
    • The resulting parts are: ["user", "zone", "custom", "region", "US", "session", "1234567", "sessionTime", "5"]
    • Authentication Check: The system compares the first part, user, to the configured Username value (e.g., "user" from the example config). The rest of the parts are completely ignored for authentication.

Configuration Example (appsettings.json)

Here’s how you would enable this feature in your appsettings.json:

{
  "Authentication": {
    // ... other authentication settings ...
    "Required": true,
    "Verify": true,
    "ParseUsernameParameters": true,
    "Username": "user",  // This is the base username to compare against
    "Password": "1111"    // Password
  }
}

Web Proxy Checker v2.111 Released

Enhanced Authentication for Problematic Proxies

We’re pleased to announce the release of Web Proxy Checker version 2.111 – our reliable tool for testing proxy server functionality now includes improved handling for CONNECT (HTTPS) proxies with non-standard authentication behavior.

Standard Proxy Authentication Flow

When connecting to a proxy requiring Basic Authentication, the expected protocol is:

  1. Client (browser or our tool) connects without credentials
  2. Proxy responds with “407 Proxy Authentication Required”
  3. Client reconnects with the Proxy-Authorization HTTP header
  4. Connection proceeds if credentials are valid

This standard flow is used by all major browsers (Chrome, Firefox, Edge) and has been Web Proxy Checker’s default behavior.

The Challenge: Non-Compliant Proxies

During testing, we identified proxies that don’t follow authentication standards. Instead of returning the proper 407 error, they immediately close connections when credentials are missing. This creates a compatibility issue where legitimate authentication attempts fail.

New Feature: “Connect Basic Authentication” Setting

Version 2.111 introduces a solution on the HTTP tab: the new “Connect Basic Authentication” option.

How it works:

  • Disabled (Default): Standard behavior – waits for 407 response before sending credentials
  • Enabled: Immediately includes Proxy-Authorization header in the first connection attempt
  • Result: Compatibility with proxies that require immediate authentication

Usage Recommendations:

  • Most users should keep this setting disabled (works with standard proxies)
  • Enable only when encountering proxies that close connections without 407 responses
  • Particularly useful for certain corporate or custom proxy setups

Quick Setup:

  1. Launch Web Proxy Checker v2.111
  2. Go to the HTTP tab
  3. Find “Connect Basic Authentication” checkbox
  4. Enable for problematic proxies, disable for standard ones

What This Means for You:

  • ✓ Wider proxy compatibility
  • ✓ No more failed connections with non-standard proxies
  • ✓ Backward compatibility maintained
  • ✓ Easy toggle between authentication modes

Upgrade Today

Download Web Proxy Checker v2.111 and experience improved compatibility with all your proxy servers!

ProxyMapService Diagnostics in Windows Event Log

ProxyMapService now supports outputting diagnostic messages directly to the Windows Event Log.


1. Enabling Event Log Logging

To enable writing events to the Windows Event Log, you need to make a small change in your project’s configuration file — appsettings.json.

Add the EventLog section within the Logging block, specifying the desired minimum logging level. The example below sets the level to “Information”:

{
  "Logging": {
    "EventLog": {
      "LogLevel": {
        "Default": "Information"
      }
    }
  }
}

💡 Note: The Default level within the EventLog section determines the minimum level (Trace, Debug, Information, Warning, Error, Critical) at which messages will be written to the log.


2. Mandatory Step: Registering the Event Source (PowerShell)

Attention! For messages to be successfully displayed in the Event Log and for the system to correctly identify their source and formatting, it is necessary to register the event source with the name ProxyMapService beforehand.

Event source registration is only required once upon installation or update of the service.

Use PowerShell run as administrator and execute the following command. This command creates the necessary registry key:

New-EventLog -LogName Application -Source ProxyMapService
  • New-EventLog: The cmdlet used to create a new event source.
  • -LogName Application: Specifies that the source will write to the standard “Application” log.
  • -Source ProxyMapService: Sets the source name, which must match the name used within the service code.

3. Viewing the Events

After configuring appsettings.json and registering the source, restart the ProxyMapService. All events at the Information level and above will now be available for viewing in the Windows Event Viewer under Windows Logs $\rightarrow$ Application.

Look for messages with the Source: ProxyMapService.

🔗 Source Code and Discussion: As always, you can find the latest version of the project on GitHub: https://github.com/optinsoft/ProxyMapService

CountryTimezone

If you’ve worked with timezones in Python, you’ve probably used pytz to get IANA timezone names for specific countries:

tz_names = pytz.country_timezones.get(country.upper(), [])

When I needed similar functionality in Delphi, I was surprised to find that there wasn’t a readily available library to get IANA timezone names for countries.

After searching without success, I decided to create my own solution:

https://github.com/optinsoft/CountryTimezone

Here’s a practical example that demonstrates how to get a random timezone name and its UTC offset for a given country:

uses CountryTimezone, TZDB;

type
   TTimezoneAndOffset = record
        name: String;
        offset: Integer;
   end;

function GetRandomTimezoneAndOffset(country: String): TTimezoneAndOffset;
var
  LCTZDict: TCountryTimezoneDictionary;
  LCTZList: TStringList;
  tz: TBundledTimeZone;
begin
  LCTZDict := TCountryTimezoneDictionary.Create();
  LCTZList := TStringList.Create;
  try
    LCTZDict.GetCountryTimezones(country, LCTZList);
    Result.name := LCTZList[Random(LCTZList.Count)];
    tz := TBundledTimeZone.GetTimeZone(Result.name);
    Result.offset := Trunc(tz.UtcOffset.TotalMinutes);
  finally
    LCTZList.Free;
    LCTZDict.Free;
  end;
end;

This function:

  1. Creates a country timezone dictionary
  2. Retrieves all timezone names for the specified country
  3. Selects a random timezone from the list
  4. Uses TZDB to get the UTC offset in minutes for that timezone

renamedecl

🔄 Renaming Variables and Functions in JavaScript Using ASTs

When working with JavaScript, there are times you might want to automatically rename variables or functions across your code — perhaps for obfuscation, code transformation, or refactoring. Doing this safely, without accidentally breaking your program, requires understanding how your code is structured — and that’s where the Abstract Syntax Tree (AST) comes in.

In this post, we’ll look at how to rename variable and function declarations using ASTs, with a simple utility renamedecl.


🌳 What Is an AST?

An Abstract Syntax Tree (AST) is a structured, tree-like representation of your source code.
Instead of dealing with raw text, you work with objects that represent program constructs like variables, functions, loops, and expressions.

For example, the code:

const x = 5;
console.log(x);

can be represented (simplified) as:

{
  type: "Program",
  body: [
    {
      type: "VariableDeclaration",
      declarations: [
        {
          type: "VariableDeclarator",
          id: { type: "Identifier", name: "x" },
          init: { type: "Literal", value: 5 }
        }
      ]
    },
    {
      type: "ExpressionStatement",
      expression: {
        type: "CallExpression",
        callee: {
          object: { name: "console" },
          property: { name: "log" }
        },
        arguments: [{ type: "Identifier", name: "x" }]
      }
    }
  ]
}

By working with this structure, you can programmatically modify parts of your code (e.g. change x to width) and then regenerate valid JavaScript source code.


🧩 Tools: Acorn, Escodegen

  • Acorn — a fast, lightweight JavaScript parser. It converts JS source code into an AST.
  • Escodegen — generates readable JavaScript code from an AST.

Scopes

Scopes — just like in real code, variables and functions in an AST exist within scopes (e.g., global, function, block). When renaming identifiers, you need to make sure you don’t accidentally rename a variable from an outer scope that has the same name.


🚀 Introducing renamedecl

renamedecl is the lightweight tool for renaming variables and functions in JS code based on an AST.

The function renameDeclarations(ast, rename, initscope?) walks through your AST, finds all declarations (variables, function names, parameters, etc.), and lets you rename them safely according to the rules you define.

It can be used in two main ways:


1. Automatic Renaming

You can rename every variable and function in a consistent way — for example, to obfuscate or anonymize code.

const acorn = require('acorn');
const escodegen = require('escodegen');
const { renameDeclarations } = require('renamedecl');

const originalCode = `
function add(x, y) {
    const result = x + y;
    return result;
}
`;

const ast = acorn.parse(originalCode, {
    ecmaVersion: 2020,
    sourceType: 'script'
});

// Rename all identifiers sequentially
renameDeclarations(
    ast,
    (id, scope) => `v${++scope.varNum}`,
    scope => { scope.varNum = 0; }
);

const newCode = escodegen.generate(ast);
console.log(newCode);

Output:

function v1(v2, v3) {
    const v1 = v2 + v3;
    return v1;
}

Here, every declared identifier got renamed with a consistent numbering scheme, respecting the correct scope hierarchy.


2. Custom Rename Mapping

You can also define your own rename map to transform specific variable or function names.

const renameMap = {
    x: 'width',
    y: 'height',
    result: 'sum'
};

renameDeclarations(ast, id => renameMap[id.name]);

This is great for refactoring, such as renaming variables to more meaningful names.


🧠 How Scoping Works

renamedecl automatically tracks scopes as it traverses the AST.
When it enters a new function or block, it creates a new scope object.
This ensures that two variables named x in different functions don’t get mixed up:

function outer() {
    const x = 10;
    function inner() {
        const x = 20;
        console.log(x);
    }
    inner();
}

Both x variables live in different scopes. The renaming logic keeps that distinction intact — so each gets its own renamed version.


🔧 Why Use This?

  • Safe — Respects JavaScript scoping rules
  • 🔍 Customizable — You control the renaming logic
  • 🧰 Tool-friendly — Works directly with standard AST tools
  • ⚙️ Flexible — Use it for obfuscation, refactoring, or static analysis

🧩 Try It Out

You can install it via npm:

npm install git+https://github.com/optinsoft/renamedecl.git

Then import and use it as shown above.


💡 Conclusion

Working with ASTs may sound intimidating at first, but with tools like Acorn, Escodegen, and utilities such as renamedecl, transforming JavaScript code becomes powerful and approachable.

By controlling variable and function names at the AST level, you can safely build tools for code analysis, transpilation, refactoring, or obfuscation — all while preserving the correctness of your original code.

How to download a Chrome extension without installing it

  1. In the Chrome Web Store, find the extension you need, for example, uBlock Origin.
  2. The extension’s URL looks like this: https://chromewebstore.google.com/detail/ublock/epcnnfbjfcgphgdmggkamkmgojdagdnn?hl=en-US&utm_source=ext_sidebar. The part epcnnfbjfcgphgdmggkamkmgojdagdnn is the extension’s unique ID.
  3. Find out your version of Chrome, for example, 141.0.7390.55.
  4. Use CURL to get the extension’s download link, replacing the extension ID (epcnnfbjfcgphgdmggkamkmgojdagdnn) and Chrome version (141.0.7390.55) with your own values:
    curl "https://clients2.google.com/service/update2/crx?response=redirect&os=win&arch=x64&os_arch=x86_64&prod=chromecrx&prodchannel=&prodversion=141.0.7390.55&lang=en-US&acceptformat=crx3,puff&x=id%3Depcnnfbjfcgphgdmggkamkmgojdagdnn%26installsource%3Dondemand%26uc&authuser=0"
  5. The result of the previous CURL command will look something like this:
    <HTML>
    <HEAD>
    <TITLE>Moved Temporarily</TITLE>
    </HEAD>
    <BODY BGCOLOR="#FFFFFF" TEXT="#000000">
    <!-- GSE Default Error -->
    <H1>Moved Temporarily</H1>
    The document has moved <A HREF="https://clients2.googleusercontent.com/crx/blobs/AcLY-yQ8Sxe7u0UiOxVYs1X2QxXnl4NGRAS6t4jJr_viP7fvXl9ARlV4ETIu1woz6O7cdB3-RBD9cYdV3APCdHY8S6kBmmk5mSnRTo0LZ8FUJQEkbk_6NnrX0EPLsAaqxNK-AMZSmuUQPLnhgEjCRn4So0hrUrRuyQSHOA/EPCNNFBJFCGPHGDMGGKAMKMGOJDAGDNN_25_5_0_0.crx?authuser=0">here</A>.
    </BODY>
    </HTML>
    The URL from which you can download the extension is: https://clients2.googleusercontent.com/crx/blobs/AcLY-yQ8Sxe7u0UiOxVYs1X2QxXnl4NGRAS6t4jJr_viP7fvXl9ARlV4ETIu1woz6O7cdB3-RBD9cYdV3APCdHY8S6kBmmk5mSnRTo0LZ8FUJQEkbk_6NnrX0EPLsAaqxNK-AMZSmuUQPLnhgEjCRn4So0hrUrRuyQSHOA/EPCNNFBJFCGPHGDMGGKAMKMGOJDAGDNN_25_5_0_0.crx?authuser=0
  6. Use CURL to download the CRX file:
    curl "https://clients2.googleusercontent.com/crx/blobs/AcLY-yQ8Sxe7u0UiOxVYs1X2QxXnl4NGRAS6t4jJr_viP7fvXl9ARlV4ETIu1woz6O7cdB3-RBD9cYdV3APCdHY8S6kBmmk5mSnRTo0LZ8FUJQEkbk_6NnrX0EPLsAaqxNK-AMZSmuUQPLnhgEjCRn4So0hrUrRuyQSHOA/EPCNNFBJFCGPHGDMGGKAMKMGOJDAGDNN_25_5_0_0.crx?authuser=0" --output uBlock.crx

gen_eth and gen_trx updates

After installing the NVIDIA GPU Computing Toolkit v13, the gen_eth and gen_trx projects started producing an error:

ImportError: DLL load failed while importing _driver: DLL load failed

The reason is that pycuda is trying to load the CUDA DLL from the bin directory:

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.0\bin

I am using the latest version of pycuda available at the moment: v2025.1.2.

pycuda\driver.py:

def _add_cuda_libdir_to_dll_path():
from os.path import dirname, join

text
cuda_path = os.environ.get("CUDA_PATH")

if cuda_path is not None:
    os.add_dll_directory(join(cuda_path, "bin"))
    return

However, in version v13 of the NVIDIA GPU Computing Toolkit, the DLLs are located in the bin\x64 directory:

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.0\bin\x64

To solve this problem, a new setting CUDA_DLL_PATH has been added to settings.ini, which contains the full path to the CUDA DLL.

settings.ini:

[settings]
CL_PATH=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\bin\Hostx64\x64
CUDA_DLL_PATH=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.0\bin\x64

The latest versions of gen_eth and gen_trx are available on GitHub:

PS. If the following error occurs:

pycuda._driver.LogicError: cuModuleLoadDataEx failed: device kernel image is invalid

then you need to update the NVIDIA video driver: https://www.nvidia.com/en-us/drivers/