Is it possible to use Python's requests
library to send a SOAP request?

- 23,794
- 27
- 122
- 225

- 5,661
- 11
- 44
- 64
-
How's this solution? http://stackoverflow.com/q/15569330/2620328 – sihrc Aug 11 '13 at 19:02
-
not supposed to use suds ; – Deepankar Bajpeyi Aug 11 '13 at 19:04
-
@DeepankarBajpeyi why not? It's the only tool suitable for the job. – Ian Stapleton Cordasco Aug 12 '13 at 03:08
-
2You can pass a `requests.Session` to [zeep](https://pypi.org/project/zeep/). – OrangeDog Nov 21 '18 at 17:29
-
@IanStapletonCordasco even in 2013 suds was dead. – OrangeDog Nov 21 '18 at 17:31
2 Answers
It is indeed possible.
Here is an example calling the Weather SOAP Service using plain requests lib:
import requests
url="http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL"
#headers = {'content-type': 'application/soap+xml'}
headers = {'content-type': 'text/xml'}
body = """<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="http://ws.cdyne.com/WeatherWS/" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns1:Body><ns0:GetWeatherInformation/></ns1:Body>
</SOAP-ENV:Envelope>"""
response = requests.post(url,data=body,headers=headers)
print response.content
Some notes:
- The headers are important. Most SOAP requests will not work without the correct headers.
application/soap+xml
is probably the more correct header to use (but the weatherservice preferstext/xml
- This will return the response as a string of xml - you would then need to parse that xml.
- For simplicity I have included the request as plain text. But best practise would be to store this as a template, then you can load it using jinja2 (for example) - and also pass in variables.
For example:
from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('myapp', 'templates'))
template = env.get_template('soaprequests/WeatherSericeRequest.xml')
body = template.render()
Some people have mentioned the suds library. Suds is probably the more correct way to be interacting with SOAP, but I often find that it panics a little when you have WDSLs that are badly formed (which, TBH, is more likely than not when you're dealing with an institution that still uses SOAP ;) ).
You can do the above with suds like so:
from suds.client import Client
url="http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL"
client = Client(url)
print client ## shows the details of this service
result = client.service.GetWeatherInformation()
print result
Note: when using suds, you will almost always end up needing to use the doctor.
Finally, a little bonus for debugging SOAP; TCPdump is your friend. On Mac, you can run TCPdump like so:
sudo tcpdump -As 0
This can be helpful for inspecting the requests that actually go over the wire.
The above two code snippets are also available as gists:

- 36,653
- 12
- 122
- 207

- 8,650
- 3
- 39
- 32
-
3what if the service requests username and password? where to note them? – Oskars Dec 09 '16 at 11:07
-
The suds code snippet now gives "suds.transport.TransportError: HTTP Error 500: Internal Server Error". Seems like the server is closed. – Louis Apr 11 '17 at 08:18
-
3@toast38coza http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL --> Server Error in '/WeatherWS' Application. Please update the example. – Wlad Apr 18 '17 at 13:21
-
1@toast38coza Where do I get information for headers and body variables in the requests example above? – Wlad Apr 18 '17 at 13:29
-
1The Suds documentation is no longer available on fedorahosted.org. Here's [a link](https://web.archive.org/web/20160310112216/https://fedorahosted.org/suds/wiki/Documentation) to a snapshot of the documentation on the Wayback Machine. – Christian Long Aug 27 '18 at 22:22
-
@toast38coza can you suggest me to any alternative of response = requests.post(url,data=body,headers=headers). you use header for this request. I want to implement same process in framework like zeep or suds. I need exact code example. – Md Mehedi Hasan May 20 '19 at 08:24
-
-
@MehediHasan Welcome to SO! You probably will not receive an answer because your comment with an exact example is too narrow. – Timo Jun 23 '21 at 13:58
-
I want to have `...` in a xml file and read from it like `..data='"""' + xml + '"""',..`, but result is `...errorCode>502\n
XML error..`. Do I need to parse xml in python here? Your example works without file. I think xml parsing is not needed here because I have xml input, not output. – Timo Jun 23 '21 at 19:03 -
Regarding my comment 12 hours ago, during sleep I got the enlightment that I do not have to parse anything but make sure that xml is `valid` and can check it with a `parser` like `minidom` in `python`. – Timo Jun 24 '21 at 07:12
-
@OrangeDog doctor is here https://suds.readthedocs.io/en/latest/README.html#fixing-broken-schema-s – adrien May 09 '23 at 14:03
Adding up to the last answer, make sure you add to the headers the following attributes:
headers={"Authorization": f"bearer {token}", "SOAPAction": "http://..."}
The authorization is meant when you need some token to access the SOAP API,
Otherwise, the SOAPAction is the action you are going to perform with the data you are sending in,
So if you don't need Authorization, then you could pop that out of the headers,
That worked pretty fine for me,

- 41
- 1