Plugin Development¶
Plugins can extend or replace functionality of various components of SearXNG.
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.
- pre search: - Plugin.pre_search
- post search: - Plugin.post_search
- on each result item: - Plugin.on_result
Below you will find some examples, for more coding examples have a look at the built-in plugins git://searx/plugins/ or Only show green hosted results.
Add Answer example¶
Here is an example of a very simple plugin that adds a “Hello World” 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 = "hello world"
    def __init__(self, plg_cfg):
        super().__init__(plg_cfg)
        self.info = PluginInfo(id=self.id, name=_("Hello"), description=_("demo plugin"))
    def post_search(self, request, search):
        return [ Answer(answer="Hello World") ]
Filter URLs example¶
The Result.filter_urls(..)
can be used to filter and/or modify URL fields.  In the following example, the
filter function my_url_filter:
def my_url_filter(result, field_name, url_src) -> bool | str:
    if "google" in url_src:
        return False              # remove URL field from result
    if "facebook" in url_src:
        new_url = url_src.replace("facebook", "fb-dummy")
        return new_url            # return modified URL
    return True                   # leave URL in field unchanged
is applied to all URL fields in the Plugin.on_result hook:
class MyUrlFilter(Plugin):
    ...
    def on_result(self, request, search, result) -> bool:
        result.filter_urls(my_url_filter)
        return True
Implementation¶
- class searx.plugins.Plugin(plg_cfg: PluginCfg)[source]¶
- Abstract base class of all Plugins. - active: ClassVar[bool]¶
- Plugin is enabled/disabled by default ( - PluginCfg.active).
 - 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¶
- Information about the plugin, see - PluginInfo.
 - log: Logger¶
- A logger object, is automatically initialized when calling the constructor (if not already set in the subclass). 
 - init(app: flask.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 method always returns - True, the method can be overwritten in the inheritances,- Trueplugin is active
- Falseplugin is inactive
 
 - pre_search(request: SXNG_Request, search: SearchWithPlugins) bool[source]¶
- Runs BEFORE the search request and returns a boolean: - Trueto continue the search
- Falseto 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: - Trueto keep the result
- Falseto remove the result from the result list
 - The - resultcan be modified to the needs.- Hint - If - Result.urlis modified,- Result.parsed_urlmust be changed accordingly:- result["parsed_url"] = urlparse(result["url"]) 
 - post_search(request: SXNG_Request, search: SearchWithPlugins) None | list[Result | LegacyResult] | EngineResults[source]¶
- Runs AFTER the search request. Can return a list of - Resultobjects 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 information 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.- 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 - queryis 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. 
 - keywords: list[str]¶
- See - Plugin.keywords
 
- class searx.plugins.PluginStorage[source]¶
- A storage for managing the plugins of SearXNG. - load_settings(cfg: dict[str, dict[str, Any]])[source]¶
- Load plugins configured in SearXNG’s settings plugins:. 
 - register(plugin: Plugin)[source]¶
- Register a - Plugin. In case of name collision (if two plugins have same ID) a- KeyErrorexception is raised.
 - init(app: flask.Flask) None[source]¶
- Calls the method - Plugin.initof each plugin in this storage. Depending on its return value, the plugin is removed from this storage or not.
 - post_search(request: SXNG_Request, search: SearchWithPlugins) None[source]¶
- Extend - search.result_container <searx.results.ResultContainer> with result items from plugins listed in- search.user_plugins.