What's new
  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

VPNMON VPNMON-R3 Custom OVPN Server List Generation Tutorials and Examples

Really sorry, @iTyPsIDg ... but this kind of low level customization to just get 1 VPN provider working really goes against what VPNMON-R3 is all about. It's meant to be used with any VPN provider that provides some level of publicly available API that you can query against, if you want to go down that level of automation. I would probably suggest writing a separate custom script that will generate an IP list that you could use to overwrite the one that VPNMON-R3 would use for that slot. Maybe run it once or twice a day to keep the list fresh based on a cron job?
Yeah, I understand. It really overcomplicates things. Thanks for all the work you've done on this.
 
Is the jquery for NordVPN broken for anyone else? I seem to be getting an error when it's executing the auto-update.... Nothing has changed in my config for at least 3 months :/

From the menu option U, I run x1 to update the server list and get the following:


[Executing Script]
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://api.nordvpn.com/v1/servers?limit=16354 | jq --raw-output '.[] | select(.locations[0].country.city.name == "New York") | .station'

jq: parse error: Invalid numeric literal at line 1, column 17391818

[0 Rows Retrieved From Source]

[Saved to VPN Client Slot 1 Server List]

[Execution Complete]
 
Is the jquery for NordVPN broken for anyone else? I seem to be getting an error when it's executing the auto-update.... Nothing has changed in my config for at least 3 months :/

From the menu option U, I run x1 to update the server list and get the following:


[Executing Script]
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://api.nordvpn.com/v1/servers?limit=16354 | jq --raw-output '.[] | select(.locations[0].country.city.name == "New York") | .station'

jq: parse error: Invalid numeric literal at line 1, column 17391818

[0 Rows Retrieved From Source]

[Saved to VPN Client Slot 1 Server List]

[Execution Complete]
This curl statement seems to work for me?

Code:
ViktorJp@GT-AX6000-3C88:/tmp/home/root# curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://api.nordvpn.com/v1/servers?limit=16
354 | jq --raw-output '.[] | select(.locations[0].country.city.name == "New York") | .station'
217.138.198.235
217.138.208.211
217.138.208.219
217.138.208.139
217.138.208.147
86.107.55.227
86.107.55.230
...

Sometimes they can have an error in their data or XML formatting output causing errors like that parse error you see. Perhaps they have already corrected it? :)
 
The full JSON downloads fine and is readable, so it doesn't appear an issue with NordVPN
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://api.nordvpn.com/v1/servers?limit=16354 -o servers.json

So, I increased the timeout values and it's working again - hopefully this is helpful for others if they encounter a similar issue
curl --silent --retry 3 --connect-timeout 10 --max-time 60 --retry-delay 1 --retry-all-errors https://api.nordvpn.com/v1/servers?limit=16354 | jq --raw-output '.[] | select(.locations[0].country.city.name == "New York") | .station'
 
The full JSON downloads fine and is readable, so it doesn't appear an issue with NordVPN
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://api.nordvpn.com/v1/servers?limit=16354 -o servers.json

So, I increased the timeout values and it's working again - hopefully this is helpful for others if they encounter a similar issue
curl --silent --retry 3 --connect-timeout 10 --max-time 60 --retry-delay 1 --retry-all-errors https://api.nordvpn.com/v1/servers?limit=16354 | jq --raw-output '.[] | select(.locations[0].country.city.name == "New York") | .station'
Nice! Glad you found a workaround ;)
 
My goal with this post is not to reinvent the wheel from all the examples @Viktor Jaep has provided for NordVPN. My goal is to provide two examples for NordVPN so that you can create your own custom server list query for WireGuard. If Viktor wants to cut/paste these instructions into the first post, be my guest. I basically took his post and modified it for WireGuard anyway.

Step 1) Nord uses a single private key for all VPN servers. You will need to visit Nord and generate an access token before you can locate your private key.
  1. Go to this NordVPN link.
  2. Click the "Set up NordVPN manually" button.
    1752941529467.png
  3. After completing the email verification, you will be directed to a page that allows you to generate an access token. Click the "Generate new token" button.
    1752941625203.png
  4. Leave the token expiration as is (private keys don't seem to change, so it is fine if it expires in 30 days). Click the "Generate token" button.
    1752941675000.png
  5. Copy the access token for use in the next step and close the pop-up dialog.
    1752941696381.png

Step 2) Obtain your private key
Bash:
curl -s -u token:"{ACCESS_TOKEN_FROM_PREVIOUS_STEP}" "https://api.nordvpn.com/v1/users/services/credentials" | jq -r .nordlynx_private_key
Use this private key in the following curl examples.

1) Top 5 Recommended WireGuard NordVPN Servers: This example shows you how to export all recommended NordVPN Server IPs that is based on a NordVPN algorithm per your location, and should be the fastest with the lowest load ... copy and paste the curl statements into an SSH window on your router to test their output.

First, determine the ID for your chosen country. (Exact number is of great importance!). The ID is in [ ] directly next to your country name.
Bash:
curl --silent "https://api.nordvpn.com/v1/servers/countries" | jq --raw-output '.[] | . as $parent | .cities[] | [$parent.name, $parent.id, .name, .id] | "\(.[0]) [\(.[1])] - \(.[2]) [\(.[3])]"'

Once you have found your Country ID, replace the ID in the curl statement below. In this example, I'm using the United States, which is ID 228. Also, replace your Private Key with the value you obtained previously. If the output creates a five-column list that looks like a CSV (example output below), you can copy/paste this statement into your VPNMON-R3 Server List Automation Slot and execute it in order to generate a list.
Bash:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors "https://api.nordvpn.com/v1/servers/recommendations?filters\[country_id\]=228&filters\[servers_groups\]\[identifier\]=legacy_standard&filters\[servers_technologies\]\[identifier\]=wireguard_udp&limit=5" | jq --raw-output '.[] | . as $parent | .technologies | .[] | select(.identifier == "wireguard_udp") | [$parent.name, $parent.station, .metadata[0].value] | "\(.[0]),\(.[1]),51820,{REPLACE_WITH_YOUR_PRIVATE_KEY},\(.[2])"'

Output:

Code:
United States #9397,185.203.218.154,51820,PRIVATE_KEY,e8LKAc+f9xEzq9Ar7+MfKRrs+gZ/4yzvpRJLRJ/VJ1w=
United States #9391,185.203.218.142,51820,PRIVATE_KEY,e8LKAc+f9xEzq9Ar7+MfKRrs+gZ/4yzvpRJLRJ/VJ1w=
United States #9392,185.203.218.144,51820,PRIVATE_KEY,e8LKAc+f9xEzq9Ar7+MfKRrs+gZ/4yzvpRJLRJ/VJ1w=

Another option, if you want to display the city and server ID in column one, looks like this (and is my preferred method):
Bash:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors "https://api.nordvpn.com/v1/servers/recommendations?filters\[country_id\]=228&filters\[servers_groups\]\[identifier\]=legacy_standard&filters\[servers_technologies\]\[identifier\]=wireguard_udp&limit=5" | jq --raw-output '.[] | . as $parent | .technologies | .[] | select(.identifier == "wireguard_udp") | [$parent.locations[].country.city.name, ($parent.name | split("#") | .[1]), $parent.station, .metadata[0].value] | "\(.[0]) #\(.[1]),\(.[2]),51820,{REPLACE_WITH_YOUR_PRIVATE_KEY},\(.[3])"'

Output:

Code:
Miami #6610,37.120.215.35,51820,PRIVATE_KEY,e8LKAc+f9xEzq9Ar7+MfKRrs+gZ/4yzvpRJLRJ/VJ1w=
Miami #9382,185.203.218.124,51820,PRIVATE_KEY,e8LKAc+f9xEzq9Ar7+MfKRrs+gZ/4yzvpRJLRJ/VJ1w=
Miami #9396,185.203.218.152,51820,PRIVATE_KEY,e8LKAc+f9xEzq9Ar7+MfKRrs+gZ/4yzvpRJLRJ/VJ1w=
Miami #5940,185.245.86.54,51820,PRIVATE_KEY,e8LKAc+f9xEzq9Ar7+MfKRrs+gZ/4yzvpRJLRJ/VJ1w=
Miami #9394,185.203.218.148,51820,PRIVATE_KEY,e8LKAc+f9xEzq9Ar7+MfKRrs+gZ/4yzvpRJLRJ/VJ1w=
 
Last edited:
My goal with this post is not to reinvent the wheel from all the examples @Viktor Jaep has provided for NordVPN. My goal is to provide two examples for NordVPN so that you can create your own custom server list query for WireGuard. If Viktor wants to cut/paste these instructions into the first post, be my guest. I basically took his post and modified it for WireGuard anyway.
This is fantastic!! Quick correction - your step 2 has a extra floating parenthesis at the end. ;) Just remove that and it will work.

Here's my CURL to grab all 2200+ NordVPN WG servers in the US. Getting ready to do crazy random resets to random WG servers across the US.

Code:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors "https://api.nordvpn.com/v1/servers?limit=16354&filters\[country_id\]=228&filters\[servers_groups\]\[identifier\]=legacy_standard&filters\[servers_technologies\]\[identifier\]=wireguard_udp" | jq --raw-output '.[] | . as $parent | .technologies | .[] | select(.identifier == "wireguard_udp") | [$parent.locations[].country.city.name, ($parent.name | split("#") | .[1]), $parent.station, .metadata[0].value] | "\(.[0]) WG #\(.[1]),\(.[2]),51820,<MY PRIVATE KEY>,\(.[3])"'

Could you please add instructions on how to initially set up your WG slot? Do you download a WG .config from NordVPN? I'm still poking around out there, and not seeing much about it.
 
This is fantastic!! Quick correction - your step 2 has a extra floating parenthesis at the end. ;) Just remove that and it will work.
Thanks! Fixed.
Could you please add instructions on how to initially set up your WG slot? Do you download a WG .config from NordVPN? I'm still poking around out there, and not seeing much about it.
You can use this to create a conf (I don't setup DNS so that it goes through the router):
Code:
# United States - Miami - us9106.nordvpn.com.conf

[Interface]
PrivateKey = {PRIVATE_KEY}
Address = 10.5.0.2/32

[Peer]
PublicKey = e8LKAc+f9xEzq9Ar7+MfKRrs+gZ/4yzvpRJLRJ/VJ1w=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = 94.140.11.25:51820
That should get anyone ready to use VPNMON-R3.
 
Thanks! Fixed.

You can use this to create a conf (I don't setup DNS so that it goes through the router):
Code:
# United States - Miami - us9106.nordvpn.com.conf

[Interface]
PrivateKey = {PRIVATE_KEY}
Address = 10.5.0.2/32

[Peer]
PublicKey = e8LKAc+f9xEzq9Ar7+MfKRrs+gZ/4yzvpRJLRJ/VJ1w=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = 94.140.11.25:51820
That should get anyone ready to use VPNMON-R3.
Oh that worked PERFECTLY! :)

1752949937597.png
 
That should get anyone ready to use VPNMON-R3.
@iTyPsIDg ... If you have time, I would love for you to please create a whole separate "VPNMON-R3 Custom Wireguard Server List Generation Tutorials and Examples" thread -- if you're up for managing it! You probably want to claim the first 5 message spots for future expansion. And assign it the "VPNMON" badge?

I think this is definitely going to require some dedicated space to explain the intricate details in getting this working... and kinda like I did with the various VPN providers, getting input from others and making sure the CURL/JQ's work... you seem to be excellent at them! And you have a great handle on Wireguard, and bending my script to your will! Hah!

Would you please do me this honor?? :)
 
@iTyPsIDg ... If you have time, I would love for you to please create a whole separate "VPNMON-R3 Custom Wireguard Server List Generation Tutorials and Examples" thread -- if you're up for managing it! You probably want to claim the first 5 message spots for future expansion. And assign it the "VPNMON" badge?

I think this is definitely going to require some dedicated space to explain the intricate details in getting this working... and kinda like I did with the various VPN providers, getting input from others and making sure the CURL/JQ's work... you seem to be excellent at them! And you have a great handle on Wireguard, and bending my script to your will! Hah!

Would you please do me this honor?? :)
Not today, but I can do that Monday.
 
Not today, but I can do that Monday.
Brilliant work. I did have a script (from reddit) that would give me a list of UK servers, but now I'm happily testing VPNMON-R3 alpha with a list of 15 more local NORD Wireguard servers.
 
My goal is to provide two examples for NordVPN so that you can create your own custom server list query for WireGuard

And you have suceeded admirably. Even a numbskull like me managed to get it working for Sydney Australia ...

Thanks very much @iTyPsIDg !!
 
Hi everybody,

I've wanted to use VPNMON since a long time ago, but never felt like it's the perfect time until just now. I'm a NordVPN subscriber, just like many others here in the forums, which seems very encouraging for me.
I've always used one OpenVPN client spot for a single country server, and the second for another country server, the only two countries that I need to switch between. And yeah, I'm limited with only two OpenVPN clients as I have the ancient RT-AC68U.

It seems like now I really need to switch servers for my network balancing purposes, so it's time to use this script, yaaay!
I started yesterday reading within the documentation and checking out the screenshots and details here and there, before I start installing and configuring VPNMON.

Now straight to the point, I was surprised that it's written in the first post here that NordVPN has their API deprecated (partially), so I just went forward and did a quick research to find any new info, alternatives, etc. regarding the NordVPN API. So that I can help and even contribute if needed or whenever needed in this regard.

@Viktor Jaep, are the statements and info in the first post here still valid and true? I've just read in their GitHub Issues section that they reimplemented the deprecated part of their API for more specific features, and it's working completely since then with version number 2. Following is the link for that particular GitHub Issue where they answered this, so please help with clarifying this if I'm misunderstanding something, or the first post really needs updating now, so that you make any updates/changes before I start using your script.

Kindly,

 
Last edited:
Hi everybody,

I've wanted to use VPNMON since a long time ago, but never felt like it's the perfect time until just now. I'm a NordVPN subscriber, just like many others here in the forums, which seems very encouraging for me.
I've always used one OpenVPN client spot for a single country server, and the second for another country server, the only two countries that I need to switch between. And yeah, I'm limited with only two OpenVPN clients as I have the ancient RT-AC68U.

It seems like now I really need to switch servers for my network balancing purposes, so it's time to use this script, yaaay!
I started yesterday reading within the documentation and checking out the screenshots and details here and there, before I start installing and configuring VPNMON.

Now straight to the point, I was surprised that it's written in the first post here that NordVPN has their API deprecated (partially), so I just went forward and did a quick research to find any new info, alternatives, etc. regarding the NordVPN API. So that I can help and even contribute if needed or whenever needed in this regard.

@Viktor Jaep, are the statements and info in the first post here still valid and true? I've just read in their GitHub Issues section that they reimplemented the deprecated part of their API for more specific features, and it's working completely since then with version number 2. Following is the link for that particular GitHub Issue where they answered this, so please help with clarifying this if I'm misunderstanding something, or the first post really needs updating now, so that you make any updates/changes before I start using your script.

Kindly,

Thanks for bringing this to light, @Tarek Yag... I have modified the wording slightly in that initial post. Yes, thankfully they published a new version shortly around the time of announcing this news. I had already replaced all the examples with the new working API URL back then as well. It's been working great since that date in 2024. NordVPN continued to be my stable, fast, go-to VPN.

Let me know if I can help answer any questions along the way of implementing VPNMON-R3! :)
 
I have modified the wording slightly in that initial post.
I just checked out your modifications, thank you!
Yes, thankfully they published a new version shortly around the time of announcing this news. I had already replaced all the examples with the new working API URL back then as well. It's been working great since that date in 2024.
Nice to hear that you already have everything updated, but I'm still wondering why aren't you using the newer API URLs?
Please note that the older and partially deprecated API is at
While the newer API is at
I don't want to dive into more details and dig for more info myself, but I thought you might be interested in digging into this yourself to make any needed and/or recommended updates to your script. I have a gut feeling that there could be something missing or needs update here or there.
Let me know if I can help answer any questions along the way of implementing VPNMON-R3!
I'll wait for your follow-up, and make sure that it's all ready before I dive into using VPNMON-R3 😆
Though, I'm very impressed with all the efforts you put into this and all of your other scripts. This gonna be the second script of yours I use in my setup, BackupMon being the first since a long time.

Kindly,
 
I just checked out your modifications, thank you!

Nice to hear that you already have everything updated, but I'm still wondering why aren't you using the newer API URLs?
Please note that the older and partially deprecated API is at

While the newer API is at

I don't want to dive into more details and dig for more info myself, but I thought you might be interested in digging into this yourself to make any needed and/or recommended updates to your script. I have a gut feeling that there could be something missing or needs update here or there.

I'll wait for your follow-up, and make sure that it's all ready before I dive into using VPNMON-R3 😆
Though, I'm very impressed with all the efforts you put into this and all of your other scripts. This gonna be the second script of yours I use in my setup, BackupMon being the first since a long time.

Kindly,
Lol. At that time, V1 was the new version. Guess I didn't read down far enough to see that they are now actually using V2. I'll see what happens changing statements from V1 to V2 tonight. Good thing is that V1 continues to work perfectly fine (for now).
 
Guess I didn't read down far enough to see that they are now actually using V2.
I guess this was the case indeed. I read all the way down that issue page looking for answers, as I was really concerned about v1 suddenly getting removed as it's already considered deprecated. Well, there you go, now!
Good thing is that V1 continues to work perfectly fine (for now).
LOL, yeah, to my surprise.
I'll see what happens changing statements from V1 to V2 tonight.
Thank you for your time in advance. You might already know from my other contributions, I'm always ready whenever you need testing and/or troubleshooting with changes or updates, I'll do whatever I have to do. But in this case particularly, before installing the script 😅
 

Latest threads

Support SNBForums w/ Amazon

If you'd like to support SNBForums, just use this link and buy anything on Amazon. Thanks!

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Back
Top