I'm using Python zeep to use SOAP to interact with Salesforce's Metadata API.

I'm attempting to start with the simplest thing possible, just log in and read a metadata object.

from zeep import Client as zClient

client = zClient('sf_config/sf_metadata_40.xml')

// readMetadata method exists, prints <zeep.client.OperationProxy object at ...>
print client.service.readMetadata

// errors because login method does not exist
print client.service.login

I know the zeep client reads the XML because it correctly knows that readMetadata exists, but I'm confused about how I am supposed to log in with my Salesforce username and password. I expected a login method to exist.

Additionally, I tried adding username and password to the construction of the client object:

from zeep.wsse.username import UsernameToken

client = zClient('sf_config/sf_metadata_40.xml',
                 wsse=UsernameToken('[email protected]', 'scary_secretPassW*rd'))

but it was unsuccessful, in that, executing the readMetadata method caused this error:
Fault: UNKNOWN_EXCEPTION: Destination URL not reset. The URL returned from login must be set in the SforceService

(The Java examples in Salesforce docs use a connection object that I'm not really sure what the Python zeep equivalent would be, so I don't have an example to go off of.)

That error brings this to mind, from the docs:

Retrieve the metadataServerUrl from the LoginResult returned by your SOAP API login() call.

But I'm not sure what the login() call is, since such a method does not exist on the client.service.

1 Answer 1


You will need to use the corresponding Partner API login() method to establish a session and get the serverURL where it is valid.

From the ServerUrl you will either need to extract the correct domain or switch it from the Partner API to the Metadata API path.

E.g. Change from




Or even better, use the LoginResult.metadataServerUrl to get the correct endpoint for the session.

  • I just found out you can use OAuth flow for Metadata API as well (I've already used it for REST API, so I'll just use the access_token from that). Docs here say you can use the "access token instead of the session ID", but doesn't say how to replace the other part you need, the Metadata Server URL (which it gets with loginResult.getMetadataServerUrl()). Is that something I can construct using the orgId, the way you do?
    – tscizzle
    Commented Jul 7, 2017 at 16:02
  • Huh, that seems like that something that warrants its own question, I'll do that, too.
    – tscizzle
    Commented Jul 7, 2017 at 16:37
  • Posted this question, in case it was outside of scope for this question's comment thread
    – tscizzle
    Commented Jul 7, 2017 at 16:46
  • @tscizzle You can get session Ids from a number of sources. They can have different scopes that can limit what they can be used for - See AuthSession.SessionType. Commented Jul 7, 2017 at 22:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .