Processing Provider Plugins
A Processing provider is the cleanest way to ship reusable geoprocessing tools inside a QGIS plugin. Instead of bolting a dialog onto a toolbar button, you register your algorithms with the Processing framework, where they appear in the Toolbox alongside native GDAL, GRASS, and QGIS algorithms. From there they gain features for free: a generated parameter dialog, batch execution, history logging, the graphical Model Designer, and the ability to be called from processing.run() in any other script. This page explains how to build that provider as part of a plugin, how the provider lifecycle fits the plugin lifecycle, and how this approach differs from dropping a standalone script into your processing scripts folder.
This cluster sits under the QGIS Plugin Development Guide pillar. If you have not yet assembled a working plugin skeleton, start with QGIS Plugin Boilerplate & Structure, because a provider needs the same __init__.py, metadata.txt, and lifecycle hooks. The provider replaces or supplements the UI-focused work covered in Qt Designer for GIS Interfaces: Processing generates the dialog for you, so you write parameters instead of widgets.
Prerequisites
- QGIS 3.34 LTR or later, with the Processing plugin enabled (it ships and activates by default).
- A working plugin package that loads cleanly, as described in Plugin Boilerplate & Structure.
- Familiarity with the
classFactory,initGui, andunloadlifecycle methods. - Comfort writing at least one algorithm class — see the child task Write a Custom Processing Algorithm in PyQGIS.
- An SVG or PNG icon for the provider (optional but recommended for Toolbox visibility).
Provider, Algorithms, and the Toolbox
A provider is a container. It holds one or more algorithm classes and exposes identity metadata — a machine-readable id, a human-readable name, and an icon. When QGIS starts the Processing registry, it asks every registered provider to load its algorithms, then groups them under the provider's name in the Toolbox tree. The diagram below shows the relationship.
The key insight is that the provider does not run anything itself. It is a registry entry that advertises algorithms. All real work happens inside the algorithm classes, each of which subclasses QgsProcessingAlgorithm and implements processAlgorithm().
Subclassing QgsProcessingProvider
The provider class overrides a handful of methods. Three are mandatory in practice: id(), name(), and loadAlgorithms(). The rest customize presentation. The loadAlgorithms() method is where you instantiate every algorithm and call addAlgorithm().
import os
from qgis.PyQt.QtGui import QIcon
from qgis.core import QgsProcessingProvider
from .area_classifier_algorithm import AreaClassifierAlgorithm
from .point_density_algorithm import PointDensityAlgorithm
class MyToolsProvider(QgsProcessingProvider):
def loadAlgorithms(self):
self.addAlgorithm(AreaClassifierAlgorithm())
self.addAlgorithm(PointDensityAlgorithm())
def id(self):
# Stable, lowercase, no spaces. Forms part of every algorithm id.
return "mytools"
def name(self):
# Human-readable label shown as the Toolbox group header.
return "My Tools"
def longName(self):
return "My Tools — vector and raster utilities"
def icon(self):
path = os.path.join(os.path.dirname(__file__), "icons", "provider.svg")
return QIcon(path)
Breakdown: id() returns a permanent identifier — never change it after release, because saved Processing models and scripts reference algorithms as provider_id:algorithm_id. name() is the display label and may change freely. loadAlgorithms() is called by the framework every time algorithms are refreshed, so it must create fresh instances; do not cache them. icon() returns a QIcon; if you omit it, the provider shows a generic gear.
Registering the Provider in initProcessing
A plugin exposes its provider through a dedicated initProcessing() method that runs alongside the usual GUI setup. Registration uses the global Processing registry, retrieved from QgsApplication.processingRegistry(). Crucially, you must remove the provider in unload() so disabling or reloading the plugin does not leave a stale entry.
from qgis.core import QgsApplication
from .provider import MyToolsProvider
class MyToolsPlugin:
def __init__(self, iface):
self.iface = iface
self.provider = None
def initProcessing(self):
"""Create and register the provider with the Processing registry."""
self.provider = MyToolsProvider()
QgsApplication.processingRegistry().addProvider(self.provider)
def initGui(self):
# Called by QGIS when the plugin is enabled.
self.initProcessing()
def unload(self):
# Symmetrical teardown — required to avoid duplicate providers on reload.
if self.provider is not None:
QgsApplication.processingRegistry().removeProvider(self.provider)
self.provider = None
Breakdown: Keeping initProcessing() separate from initGui() mirrors the convention used by the Plugin Builder template and keeps the registration logic discoverable. addProvider() triggers loadAlgorithms() immediately. The removeProvider() call in unload() is the single most common omission; without it, the Plugin Reloader will stack duplicate "My Tools" groups in the Toolbox every time you reload. Storing the provider on self and guarding with is not None makes teardown idempotent.
Grouping Algorithms Within the Provider
A provider can hold dozens of algorithms, so grouping keeps the Toolbox navigable. Grouping is controlled per algorithm, not by the provider, through the algorithm's group() and groupId() methods. Algorithms sharing the same groupId() collapse under one sub-node beneath the provider header.
# Inside an algorithm class:
def group(self):
return "Vector" # Display label for the sub-group
def groupId(self):
return "vector" # Stable identifier used for matching
Breakdown: Return an empty string from both methods to place an algorithm directly under the provider with no sub-group. As with the provider id, treat groupId() as stable and group() as cosmetic. Choose group names that read well next to native QGIS groups — "Vector geometry", "Raster terrain", "Data management" — so users can guess where your tools live. The full algorithm class that these methods belong to is built step by step in Write a Custom Processing Algorithm in PyQGIS.
Provider Icons and Branding
Icons appear in three places: the provider header in the Toolbox, each algorithm entry, and the generated algorithm dialog title bar. The provider's icon() supplies a default that algorithms inherit unless they override their own icon(). Prefer SVG so the icon scales across high-DPI displays.
import os
from qgis.PyQt.QtGui import QIcon
from qgis.core import QgsProcessingAlgorithm
class AreaClassifierAlgorithm(QgsProcessingAlgorithm):
def icon(self):
path = os.path.join(
os.path.dirname(__file__), "icons", "classify.svg")
return QIcon(path)
def svgIconPath(self):
# Used where QGIS needs a path rather than a QIcon object.
return os.path.join(
os.path.dirname(__file__), "icons", "classify.svg")
Breakdown: Resolve icon paths with os.path.dirname(__file__) rather than a relative string, because Processing does not guarantee the working directory. Implement svgIconPath() in addition to icon() so help generation and the Model Designer can locate the asset. If you compiled icons into a Qt resource file (resources_rc.py), reference them with the :/ prefix, for example QIcon(":/plugins/mytools/classify.svg").
Provider Algorithms vs. Script Algorithms
Both approaches subclass QgsProcessingAlgorithm, but they are deployed and discovered differently. A script algorithm is a single .py file dropped into the user's processing/scripts/ folder (or added via the Toolbox script editor). It appears under the built-in "Scripts" provider and requires no plugin. A provider algorithm ships inside a plugin, is grouped under your own branded provider, and is installable and updatable through the QGIS Plugin Repository.
| Aspect | Script algorithm | Provider plugin algorithm |
|---|---|---|
| Packaging | Single .py file | Full plugin package |
| Discovery | Built-in "Scripts" provider | Your named provider |
| Distribution | Manual copy or shared file | QGIS Plugin Repository |
| Grouping/branding | Limited | Full control via id/name/icon |
| Auto-update | None | Through plugin manager |
| Multiple algorithms | One file each | Many in one provider |
| Bundled resources | Awkward | Natural (icons, data, helpers) |
For a one-off utility you keep on a single workstation, a script is faster. For anything shared with a team, distributed publicly, or composed of several related tools, a provider plugin is the right unit. The algorithm code itself is nearly identical, which means you can prototype as a script and later move the same class into a provider with minimal changes. To learn how the resulting algorithms are invoked programmatically, see Run a Processing Algorithm from a Script.
Calling Your Provider's Algorithms
Once registered, your algorithms are addressable by their fully qualified id, provider_id:algorithm_id. This is what makes a provider so much more useful than a button: any script, model, or other plugin can run your tool through processing.run().
import processing
result = processing.run("mytools:areaclassifier", {
"INPUT": "/data/parcels.gpkg|layername=parcels",
"THRESHOLD": 1000.0,
"OUTPUT": "memory:classified",
})
classified_layer = result["OUTPUT"]
print(classified_layer.featureCount(), "features classified")
Breakdown: The id mytools:areaclassifier combines the provider's id() with the algorithm's name(). The parameter dictionary keys are the parameter names you defined in initAlgorithm(). Because the call goes through Processing, the algorithm participates in batch runs and can be chained — see Chaining Processing Algorithms for composing several into a pipeline. Use processing.run() for headless execution; use processing.runAndLoadResults() when you want the output added to the active project.
QGIS Version Compatibility
Examples target QGIS 3.34 LTR (Python 3.12). The provider API has been stable across recent releases.
| QGIS release | Python | Provider notes |
|---|---|---|
| 3.28 LTR | 3.9 | QgsProcessingProvider and addProvider() identical; use from qgis.PyQt.QtGui import QIcon. |
| 3.34 LTR | 3.12 | Baseline for this guide; full SVG icon support. |
| 3.40 / 3.44 | 3.12 | No breaking provider changes; Model Designer improvements benefit branded providers. |
Across all three lines, the registration pattern (QgsApplication.processingRegistry().addProvider() / removeProvider()) is unchanged, so a provider written against 3.34 loads without modification on 3.28 and 3.44.
Key Takeaways
- A provider is a registry container; the real logic lives in
QgsProcessingAlgorithmsubclasses it holds. - Override
id(),name(), andloadAlgorithms()at minimum; treatid()andgroupId()as permanent identifiers. - Register in
initProcessing()withaddProvider()and always pair it withremoveProvider()inunload(). - Group and brand algorithms through
group(),groupId(), andicon()for a navigable Toolbox. - Choose a provider plugin over a script when you need distribution, branding, auto-update, or multiple related tools.
- Registered algorithms are callable everywhere via
processing.run("provider_id:algorithm_id", {...}).
Frequently Asked Questions
Why does my provider appear twice in the Toolbox after editing the plugin?
You reloaded the plugin without calling removeProvider(). The previous instance stayed registered. Implement the symmetrical unload() shown above, then disable and re-enable the plugin once to clear the orphaned entry.
Do I need a separate dialog for each algorithm?
No. The Processing framework auto-generates a parameter dialog from the parameters you declare in initAlgorithm(). This is the main efficiency gain over the manual Qt approach in Qt Designer for GIS Interfaces.
Can one provider mix vector and raster algorithms?
Yes. A provider has no type restriction. Use distinct groupId() values such as vector and raster so the Toolbox organizes them under separate sub-nodes.
How do users find my provider's algorithms after installing the plugin?
They open the Processing Toolbox (Ctrl+Alt+T) and look for the group whose header matches your name(). Algorithms are also searchable by display name in the Toolbox filter box.
Is initProcessing() a required method name?
No, it is a convention. QGIS only calls initGui(). You may register the provider directly in initGui(), but factoring it into initProcessing() keeps the code readable and matches the Plugin Builder template.