What's new

VPNMON VPNMON-R3 Custom Server List Generation Tutorials and Examples

  • 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!

Viktor Jaep

Part of the Furniture
FULL DISCLOSURE: I absolutely SUCK at JQuery... 😋 It's not like SQL at all, which I'm pretty decent with. I think the reason I am no good at this is because the sources this data comes from is always structured very differently in JSON, so there's always a completely different way at getting at the data. If you find a better way of doing something, please feel free to post it and/or correct me.

This discussion below was created to provide more examples of how CURL + JQ statements can be used to auto-populate custom VPN Server Lists within VPNMON-R3. For instance, you may want your VPN Client Slot 1 to only connect to servers in New York City. VPN Slot 2 might be populated with all the servers within Canada. Etc. I'm providing examples of what might be possible, and how to craft these statements so you can copy/paste them directly into VPNMON-R3 with minimal effort.

As shown below, the "VPN Client Slot Server List Automation" menu allows you to View/Edit and Execute these statements, which will then pull the required VPN Server IPs from these various VPN Providers, and copy them into local server lists that VPNMON-R3 uses to reconnect your connections to.

1706068191009.png


NordVPN - API has been deprecated
NOTE: It seems that some API URLs continue to work as of Mar 5 2024, but that doesn't mean they will continue working as time goes on. Please plan for the worst that these will all be deprecated at some point: https://support.nordvpn.com/hc/en-u...uation-of-the-legacy-API-endpoints-on-NordVPN

1) All NordVPN Servers in a certain City:
In this example, I will show you how to filter all VPN Servers for a certain city... copy and paste the curl statements into an SSH window on your router to test their output.

First, determine a list of all valid countries, along with available city names within that country (Exact spelling is of great importance!)
Code:
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/city in the list, replace the city name (exact spelling) in the curl statement below. In this example, I'm using "New York". If the output creates a single list of IP addresses, you can copy/paste this statement into your VPNMON-R3 Server List Automation Slot, and execute it in order to generate a list.
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 | jq --raw-output '.[] | select(.locations[0].country.city.name == "New York") | .station'

2) All NordVPN Servers in a certain Country: This example shows you how to export all VPN Server IPs for a certain country... copy and paste the curl statements into an SSH window on your router to test their output.

First, determine the name for your country of choice. (Exact spelling is of great importance!)
Code:
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 name, replace the name in the curl statement below. In this example, I'm using "United States". If the output creates a single list of IP addresses, you can copy/paste this statement into your VPNMON-R3 Server List Automation Slot, and execute it in order to generate a list.
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 | jq --raw-output '.[] | select(.locations[0].country.name == "United States") | .station''

3) Top 5 Recommended 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 country of choice. (Exact number is of great importance!). The ID is in [ ] directly next to your country name.
Code:
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 United States, which is ID 228. If the output creates a single list of IP addresses, you can copy/paste this statement into your VPNMON-R3 Server List Automation Slot, and execute it in order to generate a list.
Code:
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&limit=5" | jq --raw-output '.[].station'

...knowing what you learned above:

4) All NordVPN servers within the US that support OpenVPN UDP protocols
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 | jq --raw-output '.[] | select((.locations[0].country.name == "United States") and (.technologies[0].id = 3)) | .station'

5.) All servers within New York City that support OpenVPN UDP protocols
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 | jq --raw-output '.[] | select((.locations[0].country.city.name == "New York") and (.technologies[0].id = 3)) | .station'

Here's a list of the technologies/IDs in case you're looking for something other than UDP:
Code:
"technologies": [
{
"id": 1,
"name": "IKEv2/IPSec",
"identifier": "ikev2",
},
{
"id": 3,
"name": "OpenVPN UDP",
"identifier": "openvpn_udp",
},
{
"id": 5,
"name": "OpenVPN TCP",
"identifier": "openvpn_tcp",
},
{
"id": 21,
"name": "HTTP Proxy (SSL)",
"identifier": "proxy_ssl",
},
{
"id": 23,
"name": "HTTP CyberSec Proxy (SSL)",
"identifier": "proxy_ssl_cybersec",
},
{
"id": 35,
"name": "Wireguard",
"identifier": "wireguard_udp",
}

NOTE: Being a bit biased and a user myself, NordVPN probably has one of the best developed API's to pull data, though it's not officially documented. Here's a GREAT site that goes into very great detail how you can run various CURL/JQ statements to get some very specific info using the API: https://sleeplessbeastie.eu/2019/02/18/how-to-use-public-nordvpn-api/


AirVPN

1) All AirVPN Servers in a certain City:
This example shows you how to export all VPN Server IPs for a certain city... copy and paste the curl statements into an SSH window on your router to test their output.

First, determine the name for your City of choice. (Exact spelling is of great importance!)
Code:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://airvpn.org/api/status/ | jq --raw-output '.servers | group_by(.location) | map(.[0].location)'

Once you have found your City name, replace the name in the curl statement below. In this example, I'm using "New York City". If the output creates a single list of IP addresses, you can copy/paste this statement into your VPNMON-R3 Server List Automation Slot, and execute it in order to generate a list.
Code:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://airvpn.org/api/status/ | jq --raw-output '.servers[] | select(.location=="New York City") | .ip_v4_in3, .ip_v4_in4'

2) All AirVPN Servers in a certain Country: This example shows you how to export all VPN Server IPs for a certain country... copy and paste the curl statements into an SSH window on your router to test their output.

First, determine the name for your country of choice. (Exact spelling is of great importance!)
Code:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://airvpn.org/api/status/ | jq --raw-output '.servers | group_by(.country_name) | map(.[0].country_name)'

Once you have found your country name, replace the name in the curl statement below. In this example, I'm using "United States". If the output creates a single list of IP addresses, you can copy/paste this statement into your VPNMON-R3 Server List Automation Slot, and execute it in order to generate a list.
Code:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://airvpn.org/api/status/ | jq --raw-output '.servers[] | select(.country_name=="United States") | .ip_v4_in3, .ip_v4_in4'
 
Last edited:
...continued:

PerfectPrivacy

1) All PerfectPrivacy VPN Servers in a certain City:
This example shows you how to export all PerfectPrivacy VPN Server hostnames for a certain city... copy and paste the curl statements into an SSH window on your router to test their output. Apologies for the rough output, but I'm extremely limited on grouping/sorting on this dataset for some reason.
Code:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://www.perfect-privacy.com/api/serverlocations.json | jq -r '.[].city'

Once you have found your City name, replace the name in the curl statement below. In this example, I'm using "New York". If the output creates a single list of IP addresses or hostnames, you can copy/paste this statement into your VPNMON-R3 Server List Automation Slot, and execute it in order to generate a list.
Code:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://www.perfect-privacy.com/api/serverlocations.json | jq -r 'path(.[] | select(.city =="New York"))[0]'

2) All PerfectPrivacy VPN Servers in a certain Country: This example shows you how to export all PerfectPrivacy VPN Server hostnames for a certain country... copy and paste the curl statements into an SSH window on your router to test their output. Again, this is very RAW... I'm limited on grouping/output based on the dataset, and my lack of understanding JQ.

First, determine the name for your country of choice. (Exact spelling is of great importance!)
Code:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://www.perfect-privacy.com/api/serverlocations.json | jq -r '.[].country'

Once you have found your country name, replace the name in the curl statement below. In this example, I'm using "U.S.A". If the output creates a single list of IP addresses or hostnames, you can copy/paste this statement into your VPNMON-R3 Server List Automation Slot, and execute it in order to generate a list.
Code:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://www.perfect-privacy.com/api/serverlocations.json | jq -r 'path(.[] | select(.country =="U.S.A"))[0]'

SurfShark

1) All SurfShark Servers in a certain City:
This example shows you how to export all SurfShark VPN Server IPs for a certain city... copy and paste the curl statements into an SSH window on your router to test their output.

First, determine the name for your City of choice. (Exact spelling is of great importance!)
Code:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://api.surfshark.com/v3/server/clusters | jq --raw-output '.[].location'

Once you have found your City name, replace the name in the curl statement below. In this example, I'm using "New York". If the output creates a single list of IP addresses or hostnames, you can copy/paste this statement into your VPNMON-R3 Server List Automation Slot, and execute it in order to generate a list.
Code:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://api.surfshark.com/v3/server/clusters | jq --raw-output '.[] | select(.location== "New York") | .connectionName'

2) All AirVPN Servers in a certain Country: This example shows you how to export all VPN Server IPs for a certain country... copy and paste the curl statements into an SSH window on your router to test their output.

First, determine the name for your country of choice. (Exact spelling is of great importance!)
Code:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://api.surfshark.com/v3/server/clusters | jq --raw-output '.[].country'

Once you have found your country name, replace the name in the curl statement below. In this example, I'm using "United States". If the output creates a single list of IP addresses or hostnames, you can copy/paste this statement into your VPNMON-R3 Server List Automation Slot, and execute it in order to generate a list.
Code:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://api.surfshark.com/v3/server/clusters | jq --raw-output '.[] | select(.country == "United States") | .connectionName'

WeVPN
(Shut down in 2023, user accounts moved to Windscribe VPN, and it does not have any API capabilities. Sorry!)

CHALLENGE:
If anyone comes up with any other handy-dandy CURL/JQ statements that blow my socks off, please post them below, and I will include your work in the [OP] above! :)
 
Last edited:
<RESERVED FOR MORE CONTENT>
 
For all the interested (thanks to @Viktor Jaep for providing me with these):

VPN: Nord VPN
Country: US
City: New York

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'

VPN: Nord VPN
Country: South Africa
City: Johannesburg

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 == "Johannesburg") | .station'

VPN: Nord VPN
Country: South Africa
City: London

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 == "London") | .station'
 
To cut down on the possibilities that when doing a "select all" for a certain country or city, and possibly getting servers in my list that my router connection preferences don't support (like TCP vs UDP, or Wireguard only, etc), I've made some progress on ways to filter out only NordVPN servers capable of OpenVPN UDP using these queries:

All servers within the US that support OpenVPN UDP protocols
Code:
curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors https://api.nordvpn.com/server | jq --raw-output '.[] | select(.country == "United States" and .features.openvpn_udp == true) | .ip_address'

All servers within New York City that support OpenVPN UDP protocols
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 | jq --raw-output '.[] | select((.locations[0].country.city.name == "New York") and (.technologies[0].id = 3)) | .station'

Here's a list of the technologies/IDs in case you're looking for something other than UDP:
Code:
"technologies": [
    {
      "id": 1,
      "name": "IKEv2/IPSec",
      "identifier": "ikev2",
    },
    {
      "id": 3,
      "name": "OpenVPN UDP",
      "identifier": "openvpn_udp",
    },
    {
      "id": 5,
      "name": "OpenVPN TCP",
      "identifier": "openvpn_tcp",
    },
    {
      "id": 21,
      "name": "HTTP Proxy (SSL)",
      "identifier": "proxy_ssl",
    },
    {
      "id": 23,
      "name": "HTTP CyberSec Proxy (SSL)",
      "identifier": "proxy_ssl_cybersec",
    },
    {
      "id": 35,
      "name": "Wireguard",
      "identifier": "wireguard_udp",
    }
 
Last edited:
Hello everyone,

I've been using NordVPN for a while and faced some challenges with the standard API when trying to select servers based on country.

I wanted to share a custom curl command that I've been using to get server recommendations from NordVPN based on specific countries. This approach has been really effective for me, especially when the normal API doesn't seem to work as expected.

Here's the one-liner command I use in a Bash-like shell:

Bash:
for id in 174 57 179 98; do curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors "https://nordvpn.com/wp-admin/admin-ajax.php?action=servers_recommendations&filters=\{\"country_id\":$id,\"servers_groups\":\[11\],\"servers_technologies\":\[3\]\}" | jq --raw-output '.[].station'; done
 
Hello everyone,

I've been using NordVPN for a while and faced some challenges with the standard API when trying to select servers based on country.

I wanted to share a custom curl command that I've been using to get server recommendations from NordVPN based on specific countries. This approach has been really effective for me, especially when the normal API doesn't seem to work as expected.

Here's the one-liner command I use in a Bash-like shell:

Bash:
for id in 174 57 179 98; do curl --silent --retry 3 --connect-timeout 3 --max-time 6 --retry-delay 1 --retry-all-errors "https://nordvpn.com/wp-admin/admin-ajax.php?action=servers_recommendations&filters=\{\"country_id\":$id,\"servers_groups\":\[11\],\"servers_technologies\":\[3\]\}" | jq --raw-output '.[].station'; done

Really nice work, @SlashGordon! This is the first time I've ever seen someone make use of this file --

"https://nordvpn.com/wp-admin/admin-ajax.php"

Never knew that was even possible! I'll have to do some more digging about that 🙂
 
So I noticed this morning that my custom NordVPN server list is now down to 0. Took a look, and when I look at the API site, it returns "deprecated". WTF.

Did some digging on NordVPN... found this: https://support.nordvpn.com/hc/en-u...uation-of-the-legacy-API-endpoints-on-NordVPN

Discontinuation of the legacy API endpoints on NordVPN​

As part of our ongoing commitment to enhance infrastructure and improve security, we wish to notify you of the upcoming deprecation of certain API endpoints on all OSes. The affected endpoints are as follows:
https://nordvpn.com/api/server/stats
https://nordvpn.com/api/files/zip
https://nordvpn.com/api/vpn/check/full
https://nordvpn.com/api/server
It is important to note that this modification will not impact the experience of users utilizing our NordVPN application obtained either directly from us or through officially recognized app stores. It should be emphasized that users who have created custom scripts or various integrations in a do-it-yourself approach may experience changes. These endpoints were not originally designed for such purposes.
To ensure a seamless transition, a range of deprecation methods will be implemented aimed at gradually decreasing the utilization of these specific API endpoints.
The deprecation process will commence on January 10, 2024, with a complete discontinuation of the legacy API endpoints scheduled for March 1, 2024. We appreciate your understanding and cooperation as we continue to strive for excellence in our services.
 
This has royally ticked me off, sent a nastygram to support, and will be determining whether or not I'm going to make a switch down the road depending on their response.
 
So in the interim before hearing from support, I've been testing, and it seems some API url's continue to work -- for now -- no guarantee how long this will last, and if they will actually shut down the whole api.nordvpn.com site entirely in the near future. I have changed the above NordVPN API instructions to reference working URL methods.

Specifically, the "https://api.nordvpn.com/v1/servers?limit=16354" method continues to work.

Secondarily, the "https://nordvpn.com/wp-admin/admin-ajax.php" method also works as noted above by @SlashGordon
 
So in the interim before hearing from support, I've been testing, and it seems some API url's continue to work -- for now -- no guarantee how long this will last, and if they will actually shut down the whole api.nordvpn.com site entirely in the near future. I have changed the above NordVPN API instructions to reference working URL methods.

Specifically, the "https://api.nordvpn.com/v1/servers?limit=16354" method continues to work.

Secondarily, the "https://nordvpn.com/wp-admin/admin-ajax.php" method also works as noted above by @SlashGordon
The are probably some NordVPN execs using your scripts. 😳
 
I just updated to R3 today. The API error explains the error messages I was getting in the R2 script.

Question: Can your script handle Wireguard? You listed that in your example for the IDs in post one.
 
I just updated to R3 today. The API error explains the error messages I was getting in the R2 script.
I posted some workarounds above... Still waiting on NordVPN to fix their issues dealing with Unbound unfortunately. I ping them every week or so.

Question: Can your script handle Wireguard? You listed that in your example for the IDs in post one.
That's only a way to identify and select Wireguard server IPs... unfortunately the script is OpenVPN only at the moment. I do have plans in the future to bring Wireguard compatibility into the mix.
 
Very nice. I look forward to that. I tried a dedicated IP from Nord for Unbound, but it still didn't work for my world, gallivanting and bypassing geo-restrictions. However, if I could use it for my banking stuff, that would be great.
 
Very nice. I look forward to that. I tried a dedicated IP from Nord for Unbound, but it still didn't work for my world, gallivanting and bypassing geo-restrictions. However, if I could use it for my banking stuff, that would be great.
I've temporarily switched over to AirVPN... Unbound over VPN works perfectly fine there, until Nord gets their act together. ;) AirVPN has been super stable... their servers rarely if ever have any hiccups compared to Nord... but they don't have much of a selection... 86 AirVPN servers across the US vs 2200+ for Nord.
 
Both methods are working so far...

I don't understand their approach without considering maintaining this API with enhancements like the KEY API etc.

If they cancel the API without an alternative solution, I will consider another provider after a long time.
 
I've also sent a friendly note to their support to consider an alternative API approach
Here's the latest I received from them today... I offered to help them test any solutions they come up with. I wish they would work on a resolution 24x7! :)

Code:
Thank you for your reply.
Our apologies for the delay, however, it seems like our team has still not resolved the issue at hand.
Furthermore, unfortunately, we would not require any input from your side regarding this case at this moment. However, in case any testing or troubleshooting from your side would be needed, rest assured we would contact you as soon as possible.
In the meanwhile, we apologize for the inconvenience, however, there is still no ETA for when the issue would be resolved.
Let us know if there is anything else we can help you with.
We are available 24/7 and we will be here for you!
 
Here's the latest I received from them today... I offered to help them test any solutions they come up with. I wish they would work on a resolution 24x7! :)

Code:
Thank you for your reply.
Our apologies for the delay, however, it seems like our team has still not resolved the issue at hand.
Furthermore, unfortunately, we would not require any input from your side regarding this case at this moment. However, in case any testing or troubleshooting from your side would be needed, rest assured we would contact you as soon as possible.
In the meanwhile, we apologize for the inconvenience, however, there is still no ETA for when the issue would be resolved.
Let us know if there is anything else we can help you with.
We are available 24/7 and we will be here for you!
Hey, atleast it is nice to know you have someone 24/7 to give you a semi-robotic response full of apologies and obfuscation.
 

Latest threads

Sign Up For SNBForums Daily Digest

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