Extension Scripts
About
The core functionality of NZBGet can be extended using extensions. NZBGet provides documented entry points for extensions. On certain events the extensions are executed, they receive information about event, do certain work and can communicate with NZBGet to give it instructions for further processing.
Installation
Using the Extension Manager
On the SETTINGS page you can easily find EXTENSION MANAGER
and use it to install the extensions you need. Make sure that the internet connection is working
and the path to the 7z in UNPACK->SevenZipCmd(required for unpacking the extensions) is correct.
The list of available extensions can be found in the
nzbget-extensions repository.
Manually, for your custom extensions
Option ScriptDir defines the location of extensions.
To make an extension available in NZBGet put the extension into this directory.
Then go to settings tab in web-interface (if you were already on settings
tab switch to downloads tab and then back to settings
tab to reread the list of available extensions from the disk).
Menu at the left of page should list all extensions found in ScriptDir.
Select an extension to review or change its options (if it has any).
Writing extension
In general, an extension consists of 2 files: manifest.json -
with all the meta-data describing the extension
and the executable file, like main.py.
manifest.json example:
{
"main": "main.py",
"name": "EMail",
"homepage": "https://github.com/nzbgetcom/Extension-EMail",
"kind": "POST-PROCESSING",
"displayName": "My EMail Extension",
"version": "2.0",
"nzbgetMinVersion": "24",
"author": "John Doe",
"license": "GNU",
"about": "Sends E-Mail notification.",
"queueEvents": "",
"taskTime": "",
"requirements": [
"This script requires Python3.8 to be installed on your system."
],
"description": ["This script sends E-Mail notification when the job is done."],
"options": [
{
"name": "Server",
"displayName": "Server",
"value": "smtp.gmail.com",
"description": ["SMTP server host."],
"select": []
},
{
"name": "Port",
"displayName": "Port",
"value": 25,
"description": ["SMTP server port (1-65535)"],
"select": [1, 65535]
},
{
"section": "Categories",
"name": "SendMail",
"displayName": "SendMail",
"value": "Always",
"description": ["When to send the message."],
"select": ["Always", "OnFailure"]
}
],
"commands": [
{
"name": "ConnectionTest",
"action": "Send Test E-Mail",
"displayName": "ConnectionTest",
"description": ["To check connection parameters click the button."]
},
{
"section": "Feeds",
"name": "ConnectionTest",
"action": "Send Test E-Mail",
"displayName": "ConnectionTest",
"description": ["To check connection parameters click the button."]
}
],
"sections": [
{
"name": "Categories",
"prefix": "Category",
"multi": true
},
{
"name": "Feeds",
"prefix": "Feed",
"multi": false
}
]
}
"main"
The name of the executable file.
For example: main.py, main.exe, MyExt.sh.
"name"
The extension name, identifier and prefix needed to
save the extension configuration options to nzbget.conf.
"homepage"
Just a link to the repository where the extension lives.
"kind"
Depending on the purpose of the extension, can be:
"kind": "POST-PROCESSING"
"kind": "SCAN"
"kind": "QUEUE"
"kind": "SCHEDULER"
"kind": "FEED"
If the extension can be used for multiple purposes the kind can be mixed, for example:
"kind": "SCAN/QUEUE"
More information about extension kinds can be found at:
"displayName"
The name that will be displayed in the web interface.
"version"
Extension version.
"nzbgetMinVersion" (optional)
NZBGet minimum required version.
"author"
Author’s name.
"license"
Extension license.
"about"
Brief description of the extension.
"description"
For more detailed description of the extension.
"queueEvents"
To describe the events that could be used by the extension, e.g.:
"queueEvents": "NZB_ADDED, NZB_DOWNLOADED"
More information can be found at QUEUE.
“requirements"
To describe the list of requirements, e.g.:
"requirements": [
"This script requires Python3.8+ to be installed on your system."
],
"options"
Let’s say we are writing an extension to send E-Mail notification. The user needs to configure the extension with options such as SMTP-Server host, port, login and password. To avoid hard-coding of these data in the extension NZBGet allows the extension to define the required options. The options are then made available on the settings page for user to configure.
In the provided manifest.json example we defined three options:
"options": [
{
"name": "Server",
"displayName": "Server",
"value": "smtp.gmail.com",
"description": ["SMTP server host."],
"select": []
},
{
"section": "Categories",
"name": "Port",
"displayName": "Port",
"value": 25,
"description": ["SMTP server port (1-65535)"],
"select": [1, 65535]
},
{
"name": "SendMail",
"displayName": "SendMail",
"value": "Always",
"description": ["When to send the message."],
"select": ["Always", "OnFailure"]
}
],
"section"property is optional. Default value is"options". Required"nzbgetMinVersion":"24".
When the user saves settings in web-interface the extension configuration options are saved to NZBGet configuration file using the extension name as prefix. For example:
EMail:Server=smtp.gmail.com
EMail:Port=25
Extension configuration options are passed using env-vars with prefix NZBPO_.
There are two env-vars for each option:
- one env-var with the name exactly as defined by the option
name; - another env-var with the name written in UPPER CASE and with special characters replaced with underscores.
For example, for option Server.Name two env-vars are passed:
NZBPO_Server.Name and NZBPO_SERVER_NAME.
In a case the user has installed the extension but have not saved the configuration, the options are not saved to configuration file yet. The extension will not get the options passed. This is a situation your extension must handle. You can either use a default settings or terminate the extension with a proper message asking the user to check and save configuration in web-interface.
Example (python):
required_options = ('NZBPO_FROM', 'NZBPO_TO', 'NZBPO_SERVER', 'NZBPO_PORT', 'NZBPO_ENCRYPTION',
'NZBPO_USERNAME', 'NZBPO_PASSWORD', 'NZBPO_FILELIST', 'NZBPO_BROKENLOG', 'NZBPO_POSTPROCESSLOG')
for optname in required_options:
if (not optname in os.environ):
print('[ERROR] Option %s is missing in configuration file. Please check script settings' % optname[6:])
sys.exit(POSTPROCESS_ERROR)
"commands"
Sometimes it may be helpful to be able to execute extensions from the settings page. For example the EMail extension could use a button “Send test email”. For other extensions something like “Validate settings” or “Cleanup database” may be useful too.
Starting from v19 it is possible to put buttons on the extension settings page. The buttons are defined as part of extension configuration, almost similar to extension configuration options:
"commands": [
{
"section": "Categories",
"name": "ConnectionTest",
"action": "Send Test E-Mail",
"displayName": "ConnectionTest",
"description": ["To check connection parameters click the button."]
}
],
This example creates a button with text “Send Test E-Mail” and description “To check connection parameters click the button.”.
When user presses the button NZBGet executes the extension in a special context passing button name via env. var NZBCP_COMMAND. The extension can check if it runs in command mode by examining this variable (python example):
# Exit codes used by NZBGet
COMMAND_SUCCESS = 93
COMMAND_ERROR = 94
# Check if the script is executed from settings page with a custom command
command = os.environ.get('NZBCP_COMMAND')
test_mode = command == 'ConnectionTest'
if command != None and not test_mode:
print('[ERROR] Invalid command ' + command)
sys.exit(COMMAND_ERROR)
if test_mode:
print('[INFO] Test connection...')
sys.exit(COMMAND_SUCCESS)
<script continues in normal mode>
During execution of the script NZBGet presents a special dialog showing extension output.
The extension must exit with one of predefined exit codes indicating success
(exit code 93) or failure (exit code 94).
User may close the progress dialog but the extension continues running in the background. All messages printed by the extension are saved to NZBGet log and are seen in web-interface on Messages tab.
"sections" (optional).
Required
"nzbgetMinVersion":"24".
Sections are used to logically organize options and commands in web-interface.
Sectionswith the reserved name"options"will be ignored.
"sections": [
{
"name": "Categories",
"prefix": "Category",
"multi": true
},
{
"name": "Feeds",
"prefix": "Feed",
"multi": false
}
]
"multi" means that options or commands can be added dynamically in web-intefrace.
"prefix" is relevant for multi sections to avoid name conflicts of options saved in nzbget.conf.
Example of a Name option saved in nzbget.conf that refers to the "Categories" section with the prefix "Category":
SpeedControl:Category1.Name=
SpeedControl:Category2.Name=
"taskTime"
For SCHEDULER extensions.
Example:
"taskTime": "*;*:00;*:30"
In that example the extension will be started at program boot (*) and then every 30 minutes.
Internationalization (i18n)
Note: Extension i18n requires NZBGet v26.3 or newer.
Extensions can provide translations for their names, descriptions, options, and commands in the language selected by the user in the WebUI.
How it works
There are three files involved in extension translation, each with a different role:
| File | Purpose |
|---|---|
manifest.json | Runtime English fallback. displayName, about, option displayName/description values are shown in the WebUI when no translation exists. |
locales.source.json | Input for the build tool. Contains English source strings that translators translate into other languages. The English text here duplicates manifest.json. |
_locales/{lang}/messages.json | Translated strings. Generated by nzbabel from locales.source.json. Loaded at runtime by the WebUI. |
locales.source.json
Create locales.source.json in the extension root directory with English source strings. This file is the input for the nzbabel build tool — it gives translators the English text and describes what each string is used for. The English text in this file must match what is in manifest.json.
{
"about": {
"message": "About EMail",
"description": "Section heading for extension description in settings. DO NOT translate 'EMail'."
},
"description": {
"message": "This script sends E-Mail notification when the job is done.",
"description": "Full description of the extension shown in settings"
},
"requirements": {
"message": "This script requires Python3.8+ to be installed on your system.",
"description": "System requirements displayed to the user"
},
"server_desc": {
"message": "SMTP server host.",
"description": "Help text for the Server option in EMail."
},
"port_desc": {
"message": "SMTP server port (1-65535)",
"description": "Help text for the Port option in EMail."
},
"connectiontest_desc": {
"message": "To check connection parameters click the button.",
"description": "Help text for the ConnectionTest command in EMail."
}
}
Key naming conventions
| Key pattern | Scope | Example |
|---|---|---|
about | Section heading above the extension description in settings | about → “About EMail” |
description | Full description shown in settings | description → “This script sends…” |
requirements | System requirements displayed to the user | requirements → “Requires Python3.8+” |
{optionname}_desc | Option help text | server_desc → “SMTP server host.” |
{commandname}_desc | Command help text | connectiontest_desc → “To check connection parameters…” |
Note:
displayNamekeys (for extension name, option labels, and command button text) are intentionally not generated bygenerate_locales.py. The WebUI’s fallback mechanism automatically displays the EnglishdisplayNamevalue frommanifest.jsonwhen a translation key is missing.
Translation workflow
- Extension author writes
locales.source.jsonwith Englishmessagevalues (matching the text inmanifest.json) and informativedescriptionfields for translators. - Build system (nzbabel) reads
locales.source.jsonand generates_locales/{lang}/messages.jsonfiles for each target language, where non-Englishmessagevalues are replaced with translations. - WebUI loads translations from
extensions/{extname}/_locales/{lang}/messages.jsonfor each installed extension and merges them with the prefixext_{extname}_(e.g.,ext_email_about). - Fallback: The
manifest.jsonvalues are always the fallback, in two scenarios:- Pre-v26.3 NZBGet: The i18n system is not present. The extension works exactly as before — all text comes from
manifest.jsonand_locales/files are ignored entirely. - v26.3+ NZBGet: If the
_locales/directory does not exist or a specific key is missing, the WebUI shows the English text frommanifest.json. The UI always shows readable text — never raw keys.
- Pre-v26.3 NZBGet: The i18n system is not present. The extension works exactly as before — all text comes from
Generation script
The NZBGet repository provides scripts/generate_locales.py to generate or update locales.source.json from manifest.json:
python3 path/to/nzbget/scripts/generate_locales.py path/to/Extension-Foo/manifest.json
In merge mode (default) the script reads an existing locales.source.json, updates message values from manifest.json, and preserves description hints for translators. Use --fresh to regenerate the file entirely.
Tips
Testing NZBGet version
NZBGet version is passed in env-var NZBOP_VERSION. Example values:
for stable version: nzbget-11.0; for testing version: nzbget-11.0-testing-r620 Example (python):
NZBGetVersion=os.environ['NZBOP_VERSION']
if NZBGetVersion[0:5] < '11.1':
print('[ERROR] This script requires NZBGet 11.1 or newer. Please update NZBGet')
sys.exit(POSTPROCESS_ERROR)
Communication with NZBGet via RPC-API
With RPC-API more things can be done than using command line. For documentation on available RPC-methods see API.
Example: obtaining post-processing log of current nzb-file (this is a short version of script Logger.py supplied with NZBGet):
import os
import sys
import datetime
from xmlrpc.client import ServerProxy
## Exit codes used by NZBGet
POSTPROCESS_SUCCESS = 93
POSTPROCESS_ERROR = 94
# To get the post-processing log we connect to NZBGet via XML-RPC
# and call method "postqueue", which returns the list of post-processing job.
# The first item in the list is current job. This item has a field 'Log',
# containing an array of log-entries.
# For more info visit https://nzbget.com/documentation/api/
# First we need to know connection info: host, port, username and password of NZBGet server.
# NZBGet passes all configuration options to post-processing script as
# environment variables.
host = os.environ["NZBOP_CONTROLIP"]
port = os.environ["NZBOP_CONTROLPORT"]
username = os.environ["NZBOP_CONTROLUSERNAME"]
password = os.environ["NZBOP_CONTROLPASSWORD"]
if host == "0.0.0.0":
host = "127.0.0.1"
# Build an URL for XML-RPC requests
rpcUrl = f"http://{username}:{password}@{host}:{port}/xmlrpc"
# Create remote server object
server = ServerProxy(rpcUrl)
# # Call remote method 'postqueue'. The only parameter tells how many log-entries to return as maximum.
postqueue = server.postqueue(10000)
# # Get field 'Log' from the first post-processing job
log = postqueue[0]["Log"]
# post proccessing log file
pplog_file = f"{os.environ['NZBPP_DIRECTORY']}/_postprocesslog.txt"
# # Now iterate through entries and save them to the output file
if len(log) > 0:
with open(pplog_file, "w") as f:
for entry in log:
timestamp = datetime.datetime.fromtimestamp(int(entry["Time"]))
output_file = f"{entry['Kind']}\t{timestamp}\t{entry['Text']}\n"
f.write(output_file)
f.close()
sys.exit(POSTPROCESS_SUCCESS)
Introduction
Installation manuals
- Installation on Windows
- Installation on Windows via WinGet
- Installation on macOS
- Installation on macOS via Homebrew
- Installation on Linux
- Installation on Docker
- Installation on Docker - LinuxServer.io version
- Installation on Android
- Installation on Synology
- Installation on QNAP
- Installation on other NAS devices
Building manuals
Configuration
- Backup And Restore Settings
- Performance Tips
- Choosing Cipher
- Behind Other Web Server
- TLS certificate verification
- What is the Default NZBGet Password?
- NZBGet Docker Setup Guide
- NZBGet Port Settings and Access Guide
- How to Configure NZBGet: Complete Setup Guide
- What Is Usenet?
- NZBGet 502 Error: Quick Fix Guide
- How to Upgrade from NZBGet v21.1 to the Latest NZBGet Version
- Slow NZBGet Speeds? Here’s How to Fix It
- NZBGet Performance Optimization Guide
- NZBGet Path and Folder Structure Guide
- How to Link NZBGet with Sonarr, Radarr, and Other Tools
- Sonarr vs VideoSort: How They Work with NZBGet
- NZBGet Storage Guide: Improve Performance with Smarter Path Setup
- How to Configure NZBGet on Android TV
- Using NZBGet with Sonarr and Radarr on Android TV
Performance tuning
- How to Optimize Usenet Performance in NZBGet
- NZBGet SystemHealth: Configuration and Environment Diagnostics
- Testing Usenet Speed and Performance in NZBGet
- Diagnosing and Maximizing Usenet Speeds in NZBGet
- Understanding Download Health in NZBGet
- Finding the Optimal Connection Count in NZBGet
- Primary vs Fill Servers Explained
- Understanding the Statistics Page in NZBGet
Usage
- Quick Filter
- Keyboard Shortcuts
- RSS and duplicate check
- VideoSort
- Console Mode
- Command Line Reference
- Performing Speed Tests
- NZBGet Interface Buttons Explained: What They Do and How to Use Them
- How to Use the NZBGet Status Tab
Development
Extensions
- Extension Scripts
- Post-processing scripts
- Scan Scripts
- Queue Scripts
- Scheduler Scripts
- Feed Scripts
- NZBGet Extension Manager: What It Is and How to Use It
- API reference
News server setup
- Astraweb
- BlockNews
- Cheapnews
- EasyNews
- Eweka
- FreeDiscussions
- Frugal Usenet
- GigaNews
- NewsDemon
- Newsgroup Ninja
- NewsgroupDirect
- Newshosting
- Pure Usenet
- SunnyUsenet
- Supernews
- theCubeNet
- ThunderNews
- TweakNews
- Usenet.Farm
- UsenetExpress
- UsenetServer
- UseNext
- ViperNews
- XLned
- XS News