diff --git a/lib/geocoder/exceptions.rb b/lib/geocoder/exceptions.rb
index 7445c662dc7aa548cc065c69452fa8f3573e0bd9..01153aaf5303a81b2e9aaa5b90e65fdf85e348d9 100644
--- a/lib/geocoder/exceptions.rb
+++ b/lib/geocoder/exceptions.rb
@@ -9,6 +9,14 @@ module Geocoder
   class OverQueryLimitError < Error
   end
 
+  class ResponseParseError < Error
+    attr_reader :response
+
+    def initialize(response)
+      @response = response
+    end
+  end
+
   class RequestDenied < Error
   end
 
diff --git a/lib/geocoder/lookups/base.rb b/lib/geocoder/lookups/base.rb
index 9f79d8a0ed2439f8aea43af753715f61c7cec22f..43f7cc55f02ff34eb5f7adc571150c225134118e 100644
--- a/lib/geocoder/lookups/base.rb
+++ b/lib/geocoder/lookups/base.rb
@@ -182,6 +182,8 @@ module Geocoder
         else
           JSON.parse(data)
         end
+      rescue => err
+        raise_error(ResponseParseError.new(data)) or warn "Geocoding API's response was not valid JSON."
       end
 
       ##
@@ -189,8 +191,6 @@ module Geocoder
       #
       def parse_raw_data(raw_data)
         parse_json(raw_data)
-      rescue
-        warn "Geocoding API's response was not valid JSON."
       end
 
       ##
diff --git a/lib/geocoder/lookups/google.rb b/lib/geocoder/lookups/google.rb
index ef1e41c75cdab9f1498263f405de10cb6696a951..9b2d98be8ff2e77333004234da7ead42e02c0b44 100644
--- a/lib/geocoder/lookups/google.rb
+++ b/lib/geocoder/lookups/google.rb
@@ -19,7 +19,8 @@ module Geocoder::Lookup
     private # ---------------------------------------------------------------
 
     def valid_response?(response)
-      status = parse_json(response.body)["status"]
+      json = parse_json(response.body)
+      status = json["status"] if json
       super(response) and ['OK', 'ZERO_RESULTS'].include?(status)
     end
 
diff --git a/lib/geocoder/lookups/okf.rb b/lib/geocoder/lookups/okf.rb
index ae45e06a4680c8e61aaf05eeae547495aff5e03a..54909bb2dcd8a330710676155193f1a905ab4f15 100644
--- a/lib/geocoder/lookups/okf.rb
+++ b/lib/geocoder/lookups/okf.rb
@@ -15,7 +15,8 @@ module Geocoder::Lookup
     private # ---------------------------------------------------------------
 
     def valid_response?(response)
-      status = parse_json(response.body)["status"]
+      json = parse_json(response.body)
+      status = json["status"] if json
       super(response) and ['OK', 'ZERO_RESULTS'].include?(status)
     end
 
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 2c197f07040b1a0f2e755cd260a129e3bac6e50d..c2140fdf45896b55a86a314eb53b40998fc54629 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -107,6 +107,10 @@ module Geocoder
         raise TimeoutError if query.text == "timeout"
         raise SocketError if query.text == "socket_error"
         raise Errno::ECONNREFUSED if query.text == "connection_refused"
+        if query.text == "invalid_json"
+          return MockHttpResponse.new(:body => 'invalid json', :code => 200)
+        end
+
         read_fixture fixture_for_query(query)
       end
     end
@@ -409,4 +413,8 @@ class MockHttpResponse
     @code = options[:code].to_s
     @body = options[:body]
   end
+
+  def [](key)
+    send key if respond_to?(key)
+  end
 end
diff --git a/test/unit/error_handling_test.rb b/test/unit/error_handling_test.rb
index 493d0ba0e937c21f9526bb14849df04a624123f1..dedbe5061248e9c337a853641266b98c0deca884 100644
--- a/test/unit/error_handling_test.rb
+++ b/test/unit/error_handling_test.rb
@@ -18,6 +18,29 @@ class ErrorHandlingTest < GeocoderTestCase
     end
   end
 
+  def test_always_raise_response_parse_error
+    Geocoder.configure(:always_raise => [Geocoder::ResponseParseError])
+    [:freegeoip, :google, :okf].each do |l|
+      lookup = Geocoder::Lookup.get(l)
+      set_api_key!(l)
+      assert_raises Geocoder::ResponseParseError do
+        lookup.send(:results, Geocoder::Query.new("invalid_json"))
+      end
+    end
+  end
+
+  def test_never_raise_response_parse_error
+    [:freegeoip, :google, :okf].each do |l|
+      lookup = Geocoder::Lookup.get(l)
+      set_api_key!(l)
+      silence_warnings do
+        assert_nothing_raised do
+          lookup.send(:results, Geocoder::Query.new("invalid_json"))
+        end
+      end
+    end
+  end
+
   def test_always_raise_timeout_error
     Geocoder.configure(:always_raise => [TimeoutError])
     Geocoder::Lookup.all_services_except_test.each do |l|