mrkeyoor.com_
Mon 21 Sept 02:02 UTC
PyPIWeb Backendupdated 19 Sept 2026

zeep review

Zeep turns a SOAP WSDL into Python service methods and schema-aware values. It loads the contract and imported XSD files, maps operation arguments into XML, sends requests through Requests or HTTPX, and converts SOAP responses back into Python objects. SOAP 1.1 and 1.2, WS-Addressing, UsernameToken, X.509 signing, complex schema types, plugins, and raw-response access are covered. Version 4.3.3 finally activates `Settings(forbid_external=True)`, blocking transitive HTTP imports and entity references from an untrusted WSDL to reduce SSRF exposure. Our pure Python install was typed and imported in 0.42 seconds.

Verdict

Zeep remains the practical Python client for a real WSDL, especially when WS-Security and imported schemas make hand-written XML risky. Use 4.3.3's external-reference block for untrusted contracts, and choose the vendor's REST API whenever it is equally supported.

We installed it

Lab card: what happened when we installed zeepScreenshot of zeep documentation
Install✓ · 0.5s12 packages on disk · 16 MB
Importimport zeep in 0.42s · pure Python · py.typed · requires Python >=3.10
Known vulns0(pip-audit)

Answers from our run

Does zeep install cleanly?

Yes. In a fresh container with an empty cache, pip install zeep finished in 0.5s, leaving 12 packages and 16 MB on disk. pip-audit reported no known vulnerabilities.

What does zeep need to run?

Python >=3.10, and nothing compiled: it is pure Python. In our run import zeep succeeded in 0.42s, and the package ships py.typed for type checkers.

zeep or suds: which should you use?

suds: Use it only when a legacy codebase already depends heavily on Suds objects and a migration is out of scope. Zeep remains the practical Python client for a real WSDL, especially when WS-Security and imported schemas make hand-written XML risky.

When should you not use zeep?

The provider has a supported REST or JSON endpoint. A SOAP stack adds WSDL parsing, XML schema behavior, and more dependencies to operate

API stability5/5The 4.x line has kept `Client`, service proxies, `Transport`, `Settings`, plugins, factories, and WS-Security helpers recognizable since 2020. Version 4.3.3 changes external-reference behavior only when the new setting is enabled, preserving the previous default. The main compatibility movement has been dropping old Python releases rather than reshaping ordinary operation calls.
Docs4/5The dedicated documentation covers WSDL inspection, transports, caching, timeouts, settings, complex values, plugins, WS-Security, signatures, async calls, and client certificates. It plainly states that AsyncClient loads WSDL documents synchronously and that lenient parsing can lose data. Some examples use public SOAP services that have aged poorly, and vendor-specific schema failures still require raw XML and source reading.
Maintenance3/5Version 4.3.3 and the repository's latest push both landed on June 18, 2026. The release fixes a meaningful SSRF boundary by wiring up external-reference blocking. The maintainer describes the project as stable with limited future development, and GitHub reports 468 open issues and pull requests. Expect focused bug fixes from good contributions rather than a predictable feature roadmap.
Ecosystem4/5The supplied current count is 9,757,013 weekly downloads, and GitHub reports 2,007 stars. Zeep covers common enterprise SOAP requirements through Requests, HTTPX, lxml, XMLSec, WS-Addressing, and WSDL tooling. Python SOAP choices are much narrower than REST choices, which strengthens Zeep's position while limiting the amount of new third-party integration work around it.

Use it if

  • A bank, carrier, government system, or ERP exposes a WSDL and requires SOAP envelopes rather than JSON
  • The contract uses imported schemas, nested complex types, SOAP 1.2, WS-Addressing, or WS-Security headers
  • You need to inspect operation signatures with `python -m zeep` before writing integration code
  • An existing Python SOAP integration needs a maintained replacement for older Suds-style clients
Skip it if

Setup reality

We installed Zeep 4.3.3 in a fresh Python 3.12 Bookworm container. pip completed in 0.5 seconds, leaving 12 packages and 16 MB on disk. Package metadata lists 11 direct dependencies, requires Python 3.10 or newer, and describes a pure Python package with py.typed and an MIT license. import zeep completed in 0.42 seconds. pip-audit found no known vulnerabilities in the resolved environment.

Client() immediately fetches the entry WSDL and its imported schemas. The default transport does not cache those documents, and document loading uses a separate timeout from SOAP operations. Create the client once, add SqliteCache when contract caching is acceptable, set both timeout and operation_timeout, and reuse the proxy. The WSDL request shares the configured Requests session, so basic auth, client certificates, private CA bundles, and proxies must be ready before construction.

Install zeep[async] for HTTPX operation calls and zeep[xmlsec] for X.509 signing. XMLSec and lxml may require native libraries or compilation on Alpine and unusual architectures even though Zeep itself is pure Python. AsyncClient's operation methods await correctly, yet WSDL loading remains synchronous. Construct it during startup or move construction off the event loop rather than doing it inside an async request handler.

For WSDL content outside your control, use Settings(forbid_external=True) in 4.3.3 and restrict the initial URL with your own allowlist. That setting refuses transitive HTTP and HTTPS imports plus external entity resolution, while still loading the URL supplied to Client. Strict mode is safer for contract fidelity. If a vendor forces strict=False, capture raw XML in tests and verify every required field because recovery parsing can discard malformed content.

Patterns

Load a WSDL and call an operation create-client

from zeep import Client

client = Client('https://partner.example/service?wsdl')
quote = client.service.GetQuote(symbol='AAPL')

Construction downloads the WSDL and imported schemas. Reuse the client rather than rebuilding it per request.

Print operation signatures inspect-wsdl

python -m zeep 'https://partner.example/service?wsdl'

The command lists bindings, namespaces, types, and operation arguments before application code is written.

Authenticate the WSDL and SOAP calls configure-auth

from requests import Session
from requests.auth import HTTPBasicAuth
from zeep import Client
from zeep.transports import Transport

session = Session()
session.auth = HTTPBasicAuth(username, password)
client = Client(wsdl_url, transport=Transport(session=session))

The same session loads the WSDL, so auth and CA settings must exist before client construction.

Bound requests and cache contracts set-timeouts-cache

from zeep.cache import SqliteCache
from zeep.transports import Transport

transport = Transport(
    cache=SqliteCache(path='/var/cache/app/zeep.db', timeout=3600),
    timeout=10,
    operation_timeout=30,
)
client = Client(wsdl_url, transport=transport)

`timeout` covers WSDL and schema loading; `operation_timeout` covers service calls. No cache is used by default.

Block transitive WSDL fetches forbid-external-imports

from zeep import Client, Settings

settings = Settings(forbid_external=True)
client = Client(allowed_wsdl_url, settings=settings)

Version 4.3.3 blocks external imports and entities. Your code must still allowlist the initial URL passed to `Client`.

Send a WS-Security UsernameToken username-token

from zeep import Client
from zeep.wsse.username import UsernameToken

client = Client(
    wsdl_url,
    wsse=UsernameToken(username, password, use_digest=True),
)

This credential lives in the SOAP header. Some providers also require separate HTTP authentication.

Create a schema-defined value construct-complex-type

factory = client.type_factory('ns0')
address = factory.Address(street='Main St 1', city='Springfield')
Order = client.get_type('ns0:Order')
order = Order(id=1, shipTo=address)
client.service.SubmitOrder(order=order)

Get namespace prefixes from the Zeep CLI output. Factory objects catch schema-shape mistakes earlier than deeply nested dictionaries.

Record the latest SOAP exchange capture-soap-xml

from lxml import etree
from zeep.plugins import HistoryPlugin

history = HistoryPlugin(maxlen=1)
client = Client(wsdl_url, plugins=[history])
client.service.Ping()
xml = etree.tostring(history.last_sent['envelope'], pretty_print=True)

Remove tokens, signatures, and business data before attaching captured envelopes to a support ticket.

Inspect an untouched HTTP response raw-response

with client.settings(raw_response=True):
    response = client.service.GetReport(reportId=42)
    response.raise_for_status()
    xml_bytes = response.content

The setting context applies only inside the block and returns a Requests response instead of a Zeep value.

Scope recovery parsing to one client lenient-parsing

from zeep import Client, Settings

client = Client(wsdl_url, settings=Settings(strict=False))
result = client.service.LegacyOperation()

The documentation warns that recover mode may lose malformed data. Assert important response fields in integration tests.

Await SOAP operations async-operation

import zeep

client = zeep.AsyncClient(wsdl_url)
try:
    result = await client.service.Ping()
finally:
    await client.transport.aclose()

Install `zeep[async]`. WSDL construction is still synchronous, so do it during startup or outside the event loop.

Convert Zeep values to plain containers serialize-response

from zeep import helpers

result = client.service.GetReport(reportId=42)
data = helpers.serialize_object(result, target_cls=dict)

Dates and datetimes remain Python objects after conversion and need a JSON encoding policy.

Alternatives

PackageRegistryPick it when
sudsPyPIUse it only when a legacy codebase already depends heavily on Suds objects and a migration is out of scope.
requestsPyPIUse it for one or two fixed operations when maintaining explicit XML templates is simpler than loading a WSDL model.
spynePyPIUse it when Python must publish a SOAP service; Zeep is a client.

More web backend guides

urllib3 · requests · ws · anyio · httpx · undici · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.