Utilities Reference
Apprise includes a set of utility helpers used across plugins and supported integrations. Plugin authors should prefer these helpers over ad hoc parsing and formatting because they provide consistent behaviour, edge case handling, and safer logging.
This page focuses on the helpers you are most likely to use when writing or maintaining plugins. Additional utilities exist, but they are intentionally not covered here.
Import Patterns
Section titled “Import Patterns”Helpers are exposed through apprise.utils (recommended for plugin
authors), and are implemented in the apprise.utils.* modules.
# Parsing and validationfrom apprise.utils.parse import ( parse_bool, parse_call_sign, parse_emails, parse_list, parse_phone_no, parse_url, parse_urls, is_call_sign, is_email, is_hostname, is_ipaddr, is_phone_no, is_uuid, validate_regex,)
# Safer debug loggingfrom apprise.utils.sanitize import sanitize_payload
# Encoding helpersfrom apprise.utils.base64 import ( base64_urlencode, base64_urldecode, encode_b64_dict, decode_b64_dict,)Recommended Calling Pattern
Section titled “Recommended Calling Pattern”A practical way to think about the parsing utilities is:
parse_*()functions split and normalize lists of inputs, often forgiving. Many accept astore_unparseableoption so you can log which values were rejected later.is_*()functions validate a single candidate value. They returnFalseon failure, otherwise they return normalized data that you can safely store.validate_regex()is a strict helper used to validate and optionally format a value using a regex match.
Most plugins use both styles together. For example, an SMS plugin can call
parse_phone_no() to break up a user-supplied target list, then call
is_phone_no() on each entry to validate and normalize it.
URL Parsing
Section titled “URL Parsing”parse_url()
Section titled “parse_url()”Use this in parse_url() or parse_native_url() implementations to convert a
user-provided URL into a normalized structure. It handles schema detection,
quoting, user and password extraction, host verification, port parsing, and
query-string parsing.
Typical usage:
from apprise.utils.parse import parse_url
results = parse_url(url, verify_host=False)if not results: return None
schema = results["schema"]host = results.get("host")qsd = results.get("qsd", {}) # query-string dictionaryKey Arguments
Section titled “Key Arguments”-
verify_host
WhenTrue,parse_url()validates the host and returnsNoneif it is missing or invalid. This is a good default for network targets. WhenFalse, host validation is relaxed, which is useful for plugins that treat the host as an identifier or do not require a host. -
default_schema
Used when a user omits theschema://portion. -
simple
WhenTrue, returns a smaller result structure. Most plugins should use the defaultsimple=False. -
plus_to_space
Controls whether+in the query string becomes a space. Apprise defaults this toFalsebecause+is common in tokens and passwords.
What It Returns
Section titled “What It Returns”The returned dictionary varies by input, but typically includes:
schema, and optionallyhostandportuserandpasswordwhen providedfullpath, and sometimespathandquery- Parsed query-string data, via
qsd
Common Parsing Helpers
Section titled “Common Parsing Helpers”parse_bool()
Section titled “parse_bool()”Converts common boolean representations into a Python bool. This is the
preferred way to parse flags from URL query strings or configuration values.
from apprise.utils.parse import parse_bool
include_image = parse_bool(qsd.get("image"), default=False)batch = parse_bool(qsd.get("batch"), default=True)What It Recognizes
Section titled “What It Recognizes”- False-like:
"0","no","off","false","deny","disable","never" - True-like:
"1","yes","on","true","allow","enable"
If a string cannot be interpreted, default is returned. For non-string values,
bool(value) is used.
Tri-state Behaviour Example
Section titled “Tri-state Behaviour Example”Sometimes you want different behaviour for:
- not provided at all (unset)
- explicitly enabled
- explicitly disabled
A common case is a feature that is auto-enabled only when another setting is present, unless the user explicitly disables it.
raw = qsd.get("discovery") # None when not provided
if raw is None: # Unset: choose a default based on other configuration discovery = True if (self.secure and self.host) else Falseelse: # Explicitly set: honor user intent discovery = parse_bool(raw, default=False)parse_list()
Section titled “parse_list()”Breaks string and list-like inputs into a single list. It accepts multiple inputs and merges them. By default it returns a sorted, unique list.
from apprise.utils.parse import parse_list
tags = parse_list(qsd.get("tag"), cast=str)targets = parse_list(qsd.get("to"), cast=str, allow_whitespace=False)Common Options
Section titled “Common Options”castconverts values before parsing when possible (useful when values may be numeric).allow_whitespacecontrols whether whitespace is treated as a delimiter.sortcontrols whether the result is normalized into a unique sorted list (True), or returned in parsed order (False).
parse_emails() and is_email()
Section titled “parse_emails() and is_email()”These helpers are commonly used in email-like integrations and anywhere a user can pass multiple recipients.
parse_emails()extracts multiple candidate emails from strings and recursively walks through tuples, lists, and sets.is_email()validates a single email and returns a structured result.
from apprise.utils.parse import parse_emails, is_email
recipients = []for candidate in parse_emails(qsd.get("to")): result = is_email(candidate) if not result: self.logger.warning("Dropped invalid email (%s) specified.", candidate) continue
recipients.append(result["full_email"])Tip: is_email() returns a dictionary (not just a boolean). When present, you
can use fields like name, domain, and full_email to build a canonical
representation and keep name mappings for later.
parse_urls()
Section titled “parse_urls()”Extracts URLs from strings or list-like input and can preserve unparseable entries to aid error reporting.
from apprise.utils.parse import parse_urls
endpoints = parse_urls(qsd.get("endpoint"))How store_unparseable Helps
Section titled “How store_unparseable Helps”If no valid items are detected and store_unparseable=True, the input is split
on common delimiters and returned anyway. This allows you to log which values
were rejected, rather than silently discarding everything.
A practical plugin pattern:
emails = parse_emails(qsd.get("to"), store_unparseable=True)
valid = []invalid = []for entry in emails: if is_email(entry): valid.append(entry) else: invalid.append(entry)
for entry in invalid: self.logger.warning("Ignoring invalid email: %s", entry)parse_phone_no() and is_phone_no()
Section titled “parse_phone_no() and is_phone_no()”Used by SMS, voice, and telecom-style plugins.
parse_phone_no() splits a target list into candidate entries, then
is_phone_no() validates a single entry and returns False or a dictionary.
from apprise.utils.parse import parse_phone_no, is_phone_no
valid = []invalid = []
for candidate in parse_phone_no(targets): result = is_phone_no(candidate) if result: valid.append(f"+{result['full']}") else: invalid.append(candidate)
for candidate in invalid: self.logger.warning("Dropped invalid phone number (%s) specified.", candidate)is_phone_no() result dictionary commonly includes:
full(digits only)pretty(human-friendly formatting, when available)country,area,line(may be empty)
Important constraints:
- The digit count must be between
min_len(default10) and14inclusive. - Common separators are accepted on input; you should store the normalized form.
parse_call_sign() and is_call_sign()
Section titled “parse_call_sign() and is_call_sign()”Used by APRS and ham radio-style integrations.
parse_call_sign() splits a callsign list, then is_call_sign() validates a
single callsign and returns False or a dictionary.
from apprise.utils.parse import parse_call_sign, is_call_sign
targets = []for candidate in parse_call_sign(qsd.get("to")): result = is_call_sign(candidate) if not result: self.logger.warning("Dropping invalid call sign (%s).", candidate) continue
targets.append(result["callsign"].upper())is_call_sign() validates a single callsign and returns False or a dictionary:
callsign(uppercased)ssid(string, may be empty)
A practical pattern mirrors phone and email handling:
- Parse a list with
parse_call_sign(...) - Validate each entry with
is_call_sign(...) - Warn on invalid values, do not fail the entire configuration unless the service requires at least one valid target
Host and Identifier Validation
Section titled “Host and Identifier Validation”These helpers are frequently used by plugins to validate inputs early and produce clear error messages.
-
is_hostname(hostname, ipv4=True, ipv6=True, underscore=True)
Validates hostnames and optionally IP addresses. It supports underscores whenunderscore=Trueto accommodate practical Docker and local naming conventions. -
is_ipaddr(addr, ipv4=True, ipv6=True)
Validates IPv4 and IPv6. For IPv6, it returns the address enclosed in brackets ([addr]) to align with URL formatting expectations. -
is_uuid(value)
Validates UUID strings.
These helpers return False when invalid. When valid, they return a normalized
string (not a boolean).
Regex Validation
Section titled “Regex Validation”validate_regex()
Section titled “validate_regex()”Validates a value against a regular expression. On success it returns the
(cleaned) value, otherwise it returns None.
from apprise.utils.parse import validate_regex
token = validate_regex(qsd.get("token"), r"^[A-Z0-9]{32}$", flags="i")if not token: self.logger.warning("An invalid token was specified") return NonePlugin template_token Regex Tuples
Section titled “Plugin template_token Regex Tuples”If your plugin defines a template token regex (as most plugins do), you can reuse it directly when validating inputs, which keeps the definition in one place.
Example pattern:
self.token = validate_regex( token, *self.template_tokens["token"]["regex"])This relies on template_tokens["token"]["regex"] being a tuple in the form
(regex, flags).
Notable Features
Section titled “Notable Features”- Regexes are cached internally after compilation, so repeated validations are inexpensive.
flagsmay be passed as an integer, or as a string of flag characters, for example"imx".- When
fmtis provided, named capture groups can be reassembled into a normalized string.
Example with formatting:
value = validate_regex( value="prefix-123", regex=r"^(?P<prefix>[a-z]+)-(?P<id>[0-9]+)$", flags="i", fmt="{prefix}:{id}",)# value is now "prefix:123" (or None if no match)Safe Logging and Secret Handling
Section titled “Safe Logging and Secret Handling”sanitize_payload()
Section titled “sanitize_payload()”Use this helper before logging request payloads or response details, especially when the structure may include attachments, large encoded blobs, or deep nesting. It reduces log pollution and avoids leaking sensitive or very large values, while still preserving enough structure to troubleshoot.
from apprise.utils.sanitize import sanitize_payload
self.logger.debug("payload=%s", sanitize_payload(payload))When to Use It
Section titled “When to Use It”You do not need to sanitize every debug log. sanitize_payload() is most
useful when:
- a payload might contain attachments (base64, bytes, file metadata)
- a response might contain unexpectedly large objects
- you want safe previews without copying large values into logs
If your debug log could be heavy, guard the call so it only runs when debug logging is enabled.
import loggingfrom apprise.utils.sanitize import sanitize_payload
if self.logger.isEnabledFor(logging.DEBUG): self.logger.debug("Payload: %s", sanitize_payload(payload))What It Does
Section titled “What It Does”- Leaves primitives unchanged (e.g.,
None, booleans, numbers). - Summarizes long strings with a compact marker and head and tail previews.
- Summarizes bytes with a bounded sha256 digest marker.
- Walks nested dictionaries and sequences safely.
- Detects recursion and prevents infinite traversal.
- Applies depth and item limits to prevent excessively large logs.
Practical pattern:
- Build your request payload normally.
- If debug is enabled, log
sanitize_payload(payload). - Send the original payload to the upstream service.
Tuning Behaviour
Section titled “Tuning Behaviour”Some environments benefit from stricter bounds, for example to prevent large attachments or Base64-like blobs from entering logs.
from apprise.utils.sanitize import SanitizeOptions, sanitize_payload
opts = SanitizeOptions( max_str_len=64, preview=8, max_depth=4, max_items=250,)
self.logger.debug("payload=%s", sanitize_payload(payload, options=opts))When troubleshooting, avoid raising these limits globally. A safer approach is to temporarily adjust them locally around a specific debug log statement.
Encoding Helpers
Section titled “Encoding Helpers”base64_urlencode() and base64_urldecode()
Section titled “base64_urlencode() and base64_urldecode()”URL-safe Base64 helpers for working with bytes.
from apprise.utils.base64 import base64_urlencode, base64_urldecode
encoded = base64_urlencode(b"abc") # "YWJj"decoded = base64_urldecode(encoded) # b"abc"These helpers are strict about input types. They return None for unsupported
inputs.
encode_b64_dict() and decode_b64_dict()
Section titled “encode_b64_dict() and decode_b64_dict()”Dictionary helpers used when an API expects Base64-wrapped payload components,
often for binary-safe transport. Values that can be JSON-encoded are converted
to strings and wrapped with a b64: prefix.
from apprise.utils.base64 import encode_b64_dict, decode_b64_dict
original = {"int": 1, "float": 2.3}encoded, needs_decoding = encode_b64_dict(original)
# encoded == {"int": "b64:MQ==", "float": "b64:Mi4z"}# needs_decoding is True
decoded = decode_b64_dict(encoded)# decoded == originalIf JSON encoding fails for a value, the helper falls back to string conversion and will indicate that decoding is not required.
Questions or Feedback?
Documentation
Notice a typo or an error? Report it or contribute a fix .
Technical Issues
Having trouble with the code? Open an issue on GitHub: