Plugin Development

Plugins can extend or replace functionality of various components of SearXNG. Here is an example of a very simple plugin that adds a “Hello” into the answer area:

from flask_babel import gettext as _
from searx.plugins import Plugin
from searx.result_types import Answer

class MyPlugin(Plugin):

    id = "self_info"
    default_on = True

    def __init__(self):
        super().__init__()
        info = PluginInfo(id=self.id, name=_("Hello"), description=_("demo plugin"))

    def post_search(self, request, search):
        return [ Answer(answer="Hello") ]

Entry points (hooks) define when a plugin runs. Right now only three hooks are implemented. So feel free to implement a hook if it fits the behaviour of your plugin / a plugin doesn’t need to implement all the hooks.

For a coding example have a look at Self-Info.


class searx.plugins.Plugin[source]

Abstract base class of all Plugins.

default_on: ClassVar[bool]

Plugin is enabled/disabled by default.

keywords: list[str] = []

Keywords in the search query that activate the plugin. The keyword is the first word in a search query. If a plugin should be executed regardless of the search query, the list of keywords should be empty (which is also the default in the base class for Plugins).

info: PluginInfo

Informations about the plugin, see PluginInfo.

id: ClassVar[str]

The ID (suffix) in the HTML form.

log: Logger

A logger object, is automatically initialized when calling the constructor (if not already set in the subclass).

init(app: Flask) bool[source]

Initialization of the plugin, the return value decides whether this plugin is active or not. Initialization only takes place once, at the time the WEB application is set up. The base methode always returns True, the methode can be overwritten in the inheritances,

  • True plugin is active

  • False plugin is inactive

Runs BEFORE the search request and returns a boolean:

  • True to continue the search

  • False to stop the search

on_result(request: SXNG_Request, search: SearchWithPlugins, result: Result) bool[source]

Runs for each result of each engine and returns a boolean:

  • True to keep the result

  • False to remove the result from the result list

The result can be modified to the needs.

Hint

If Result.url is modified, Result.parsed_url must be changed accordingly:

result["parsed_url"] = urlparse(result["url"])

Runs AFTER the search request. Can return a list of Result objects to be added to the final result list.

class searx.plugins.PluginInfo(id: str, name: str, description: str, preference_section: ~typing.Literal['general', 'ui', 'privacy', 'query'] | None = 'general', examples: list[str] = <factory>, keywords: list[str] = <factory>)[source]

Object that holds informations about a plugin, these infos are shown to the user in the Preferences menu.

To be able to translate the information into other languages, the text must be written in English and translated with flask_babel.gettext.

id: str

The ID-selector in HTML/CSS #<id>.

name: str

Name of the plugin.

description: str

Short description of the answerer.

preference_section: Literal['general', 'ui', 'privacy', 'query'] | None = 'general'

Section (tab/group) in the preferences where this plugin is shown to the user.

The value query is reserved for plugins that are activated via a keyword as part of a search query, see:

Those plugins are shown in the preferences in tab Special Queries.

examples: list[str]

List of short examples of the usage / of query terms.

keywords: list[str]

See Plugin.keywords

class searx.plugins.PluginStorage[source]

A storage for managing the plugins of SearXNG.

legacy_plugins = ['ahmia_filter', 'calculator', 'hostnames', 'oa_doi_rewrite', 'tor_check', 'tracker_url_remover', 'unit_converter']

Internal plugins implemented in the legacy style (as module / deprecated!).

plugin_list: set[Plugin]

The list of Plugins in this storage.

load_builtins()[source]

Load plugin modules from:

register(plugin: Plugin)[source]

Register a Plugin. In case of name collision (if two plugins have same ID) a KeyError exception is raised.

register_by_fqn(fqn: str)[source]

Register a Plugin via its fully qualified class name (FQN). The FQNs of external plugins could be read from a configuration, for example, and registered using this method

init(app: Flask) None[source]

Calls the method Plugin.init of each plugin in this storage. Depending on its return value, the plugin is removed from this storage or not.

Extend search.result_container <searx.results.ResultContainer> with result items from plugins listed in search.user_plugins.

class searx.plugins._core.ModulePlugin(mod: ModuleType)[source]

Bases: Plugin

A wrapper class for legacy plugins.

Note

For internal use only!

In a module plugin, the follwing names are mapped:

  • module.query_keywords –> Plugin.keywords

  • module.plugin_id –> Plugin.id

  • module.logger –> Plugin.log

init(app: Flask) bool[source]

Initialization of the plugin, the return value decides whether this plugin is active or not. Initialization only takes place once, at the time the WEB application is set up. The base methode always returns True, the methode can be overwritten in the inheritances,

  • True plugin is active

  • False plugin is inactive

Runs BEFORE the search request and returns a boolean:

  • True to continue the search

  • False to stop the search

on_result(request: SXNG_Request, search: SearchWithPlugins, result: Result) bool[source]

Runs for each result of each engine and returns a boolean:

  • True to keep the result

  • False to remove the result from the result list

The result can be modified to the needs.

Hint

If Result.url is modified, Result.parsed_url must be changed accordingly:

result["parsed_url"] = urlparse(result["url"])

Runs AFTER the search request. Can return a list of Result objects to be added to the final result list.