How to escape @ in a password in pymongo connection?
<p>My question is a specification of <a href="http://stackoverflow.com/questions/29508162/how-can-i-validate-username-password-for-mongodb-authentication-through-pymongo">how can i validate username password for mongodb authentication through pymongo?</a>.</p>

<p>I'm trying to connect to a MongoDB instance using PyMongo 3.2.2 and a URL that contains the user and password, as explained in <a href="https://docs.mongodb.com/manual/reference/connection-string/#standard-connection-string-format" rel="nofollow">MongoDB Docs</a>. The difference is that the password I'm using contains a '@'.</p>

<p>At first I simply tried to connect without escaping, like this:</p>

<blockquote>
  <p>prefix = 'mongodb://'</p>
  
  <p>user = 'user:passw_with_@_'</p>
  
  <p>suffix = '@127.0.0.1:27001/'</p>
  
  <p>conn = pymongo.MongoClient(prefix + user + suffix)</p>
</blockquote>

<p>Naturally I got the following error: </p>

<pre><code>InvalidURI: ':' or '@' characters in a username or password must be escaped according to RFC 2396.
</code></pre>

<p>So I tried escaping the user:pass part using <a href="https://docs.python.org/2/library/urllib.html?highlight=urllib#urllib.quote" rel="nofollow">urllib.quote()</a> like this:</p>

<blockquote>
  <p>prefix = 'mongodb://'</p>
  
  <p>user = urllib.quote('user:passw_with_@_')</p>
  
  <p>suffix = '@127.0.0.1:27001/'</p>
  
  <p>conn = pymongo.MongoClient(prefix + user + suffix)</p>
</blockquote>

<p>but then I got a: </p>

<pre><code>OperationFailure: Authentication failed.
</code></pre>

<p>(Important to say that using a GUI MongoDB Management Tool (<a href="https://robomongo.org/" rel="nofollow">Robomongo</a>, if that matters) I'm able to connect to the MongoDB using the (real) address and credentials.)</p>

<p>Printing user variable in the code above generated a <code>'user:passw_with_%40_'</code> String (that is '@' became '%40') and according to <a href="https://en.wikipedia.org/wiki/Percent-encoding#Percent-encoding_reserved_characters" rel="nofollow">wikipedia</a> that's the expected escaping.</p>

<p>I even tried escaping the @ with single and double backslashes (<code>user = 'user:passw_with_\\@_'</code> and <code>user = 'user:passw_with_\@_'</code>), but those failed with the InvalidURI exception.</p>

<p><strong>TL;DR;</strong></p>

<p>My question is: How do I escape a '@' in the password part of a MongoDB URL?</p>

<p>You should be able to escape the password using <code>urllib.quote()</code>. Although you should only quote/escape the password, and exclude the <code>username:</code> ;
otherwise the <code>:</code> will also be escaped into <code>%3A</code>. </p>

<p>For example: </p>

<pre><code>import pymongo 
import urllib 

mongo_uri = "mongodb://username:" + urllib.quote("p@ssword") + "@127.0.0.1:27001/"
client = pymongo.MongoClient(mongo_uri)
</code></pre>

<p>The above snippet was tested for MongoDB v3.2.x, Python v2.7, and <a href="https://api.mongodb.com/python/current/" rel="nofollow">PyMongo</a> v3.2.2. </p>

<p>The example above assumed in the <a href="https://docs.mongodb.com/manual/reference/connection-string/" rel="nofollow">MongoDB URI connection string</a>: </p>

<ul>
<li>The user is created in the <code>admin</code> database. </li>
<li>The host <code>mongod</code> running on is 127.0.0.1 (localhost) </li>
<li>The port <code>mongod</code> assigned to is 27001</li>
</ul>

python mongodb authentication pymongo-3.x