.netrc support
diff --git a/HISTORY.rst b/HISTORY.rst
index 2091ac8499..d6b8f49690 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -1,6 +1,11 @@
 History
 -------
 
+0.10.4 (2012-02-20)
++++++++++++++++++++
+
+* Honor netrc.
+
 0.10.3 (2012-02-20)
 +++++++++++++++++++
 
diff --git a/docs/index.rst b/docs/index.rst
index df0f1937c2..232d683046 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -72,6 +72,7 @@ Requests is ready for today's web.
 - Unicode Response Bodies
 - Multipart File Uploads
 - Connection Timeouts
+- ``.netrc`` support
 
 
 User Guide
diff --git a/requests/models.py b/requests/models.py
index 2c0b2e08a5..a238214a24 100644
--- a/requests/models.py
+++ b/requests/models.py
@@ -27,7 +27,7 @@
     URLRequired, SSLError)
 from .utils import (
     get_encoding_from_headers, stream_untransfer, guess_filename, requote_uri,
-    dict_from_string, stream_decode_response_unicode)
+    dict_from_string, stream_decode_response_unicode, get_netrc_auth)
 from .compat import (
     urlparse, urlunparse, urljoin, urlsplit, urlencode, str, bytes,
     SimpleCookie, is_py2)
@@ -435,6 +435,10 @@ def send(self, anyway=False, prefetch=False):
         if (content_type) and (not 'content-type' in self.headers):
             self.headers['Content-Type'] = content_type
 
+        # Use .netrc auth if none was provided.
+        if not self.auth:
+            self.auth = get_netrc_auth(url)
+
         if self.auth:
             if isinstance(self.auth, tuple) and len(self.auth) == 2:
                 # special-case basic HTTP auth
diff --git a/requests/sessions.py b/requests/sessions.py
index 7aafd0ea5d..29ae1d9aeb 100644
--- a/requests/sessions.py
+++ b/requests/sessions.py
@@ -40,7 +40,7 @@ def merge_kwargs(local_kwarg, default_kwarg):
     kwargs.update(local_kwarg)
 
     # Remove keys that are set to None.
-    for (k,v) in list(local_kwarg.items()):
+    for (k, v) in list(local_kwarg.items()):
         if v is None:
             del kwargs[k]
 
diff --git a/requests/utils.py b/requests/utils.py
index 97f5860036..68efa4697a 100644
--- a/requests/utils.py
+++ b/requests/utils.py
@@ -11,15 +11,49 @@
 
 import cgi
 import codecs
+import os
 import random
 import re
 import zlib
+from netrc import netrc, NetrcParseError
 
 from .compat import parse_http_list as _parse_list_header
-from .compat import quote, cookielib, SimpleCookie, is_py2
+from .compat import quote, cookielib, SimpleCookie, is_py2, urlparse
 from .compat import basestring, bytes
 
 
+NETRC_FILES = ('.netrc', '_netrc')
+
+
+def get_netrc_auth(url):
+    """Returns the Requests tuple auth for a given url from netrc."""
+
+    locations = (os.path.expanduser('~/{0}'.format(f)) for f in NETRC_FILES)
+    netrc_path = None
+
+    for loc in locations:
+        if os.path.exists(loc) and not netrc_path:
+            netrc_path = loc
+
+    # Abort early if there isn't one.
+    if netrc_path is None:
+        return netrc_path
+
+    ri = urlparse(url)
+
+    # Strip port numbers from netloc
+    host = ri.netloc.split(':')[0]
+
+    try:
+        _netrc = netrc(netrc_path).authenticators(host)
+        if _netrc:
+            # Return with login / password
+            login_i = (0 if _netrc[0] else 1)
+            return (_netrc[login_i], _netrc[2])
+    except NetrcParseError:
+        pass
+
+
 def dict_from_string(s):
     """Returns a MultiDict with Cookies."""
 
@@ -149,7 +183,7 @@ def header_expand(headers):
         headers = list(headers.items())
     elif isinstance(headers, basestring):
         return headers
-    elif isinstance(headers, unicode):
+    elif isinstance(headers, str):
         # As discussed in https://github.com/kennethreitz/requests/issues/400
         # latin-1 is the most conservative encoding used on the web. Anyone
         # who needs more can encode to a byte-string before calling
