diff --git a/src/json.hpp b/src/json.hpp
index 32ec78c7..cbcdef93 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -3071,8 +3071,11 @@ class parser
 
     /// a parser reading from an input adapter
     explicit parser(detail::input_adapter_t adapter,
-                    const parser_callback_t cb = nullptr)
-        : callback(cb), m_lexer(adapter) {}
+                    const parser_callback_t cb = nullptr,
+                    const bool allow_exceptions_ = true)
+        : callback(cb), m_lexer(adapter),
+          allow_exceptions(allow_exceptions_)
+    {}
 
     /*!
     @brief public parser interface
@@ -3092,12 +3095,20 @@ class parser
         parse_internal(true, result);
         result.assert_invariant();
 
+        // in strict mode, input must be completely read
         if (strict)
         {
             get_token();
             expect(token_type::end_of_input);
         }
 
+        // in case of an error, return discarded value
+        if (errored)
+        {
+            result = value_t::discarded;
+            return;
+        }
+
         // set top-level value to null if it was discarded by the callback
         // function
         if (result.is_discarded())
@@ -3176,7 +3187,10 @@ class parser
                 while (true)
                 {
                     // store key
-                    expect(token_type::value_string);
+                    if (not expect(token_type::value_string))
+                    {
+                        return;
+                    }
                     const auto key = m_lexer.get_string();
 
                     bool keep_tag = false;
@@ -3195,7 +3209,10 @@ class parser
 
                     // parse separator (:)
                     get_token();
-                    expect(token_type::name_separator);
+                    if (not expect(token_type::name_separator))
+                    {
+                        return;
+                    }
 
                     // parse and add value
                     get_token();
@@ -3216,7 +3233,10 @@ class parser
                     }
 
                     // closing }
-                    expect(token_type::end_object);
+                    if (not expect(token_type::end_object))
+                    {
+                        return;
+                    }
                     break;
                 }
 
@@ -3273,7 +3293,10 @@ class parser
                     }
 
                     // closing ]
-                    expect(token_type::end_array);
+                    if (not expect(token_type::end_array))
+                    {
+                        return;
+                    }
                     break;
                 }
 
@@ -3334,8 +3357,15 @@ class parser
                 // throw in case of infinity or NAN
                 if (JSON_UNLIKELY(not std::isfinite(result.m_value.number_float)))
                 {
-                    JSON_THROW(out_of_range::create(406, "number overflow parsing '" +
-                                                    m_lexer.get_token_string() + "'"));
+                    if (allow_exceptions)
+                    {
+                        JSON_THROW(out_of_range::create(406, "number overflow parsing '" +
+                                                        m_lexer.get_token_string() + "'"));
+                    }
+                    else
+                    {
+                        expect(token_type::uninitialized);
+                    }
                 }
                 break;
             }
@@ -3343,14 +3373,20 @@ class parser
             case token_type::parse_error:
             {
                 // using "uninitialized" to avoid "expected" message
-                expect(token_type::uninitialized);
+                if (not expect(token_type::uninitialized))
+                {
+                    return;
+                }
                 break; // LCOV_EXCL_LINE
             }
 
             default:
             {
                 // the last token was unexpected; we expected a value
-                expect(token_type::literal_or_value);
+                if (not expect(token_type::literal_or_value))
+                {
+                    return;
+                }
                 break; // LCOV_EXCL_LINE
             }
         }
@@ -3455,10 +3491,15 @@ class parser
                 }
             }
 
+            case token_type::value_float:
+            {
+                // reject infinity or NAN
+                return std::isfinite(m_lexer.get_number_float());
+            }
+
             case token_type::literal_false:
             case token_type::literal_null:
             case token_type::literal_true:
-            case token_type::value_float:
             case token_type::value_integer:
             case token_type::value_string:
             case token_type::value_unsigned:
@@ -3483,14 +3524,23 @@ class parser
     /*!
     @throw parse_error.101 if expected token did not occur
     */
-    void expect(token_type t)
+    bool expect(token_type t)
     {
         if (JSON_UNLIKELY(t != last_token))
         {
             errored = true;
             expected = t;
-            throw_exception();
+            if (allow_exceptions)
+            {
+                throw_exception();
+            }
+            else
+            {
+                return false;
+            }
         }
+
+        return true;
     }
 
     [[noreturn]] void throw_exception() const
@@ -3527,6 +3577,8 @@ class parser
     bool errored = false;
     /// possible reason for the syntax error
     token_type expected = token_type::uninitialized;
+    /// whether to throw exceptions in case of errors
+    const bool allow_exceptions = true;
 };
 
 ///////////////
@@ -12823,10 +12875,11 @@ class basic_json
     @since version 2.0.3 (contiguous containers)
     */
     static basic_json parse(detail::input_adapter i,
-                            const parser_callback_t cb = nullptr)
+                            const parser_callback_t cb = nullptr,
+                            const bool allow_exceptions = true)
     {
         basic_json result;
-        parser(i, cb).parse(true, result);
+        parser(i, cb, allow_exceptions).parse(true, result);
         return result;
     }
 
@@ -12834,10 +12887,11 @@ class basic_json
     @copydoc basic_json parse(detail::input_adapter, const parser_callback_t)
     */
     static basic_json parse(detail::input_adapter& i,
-                            const parser_callback_t cb = nullptr)
+                            const parser_callback_t cb = nullptr,
+                            const bool allow_exceptions = true)
     {
         basic_json result;
-        parser(i, cb).parse(true, result);
+        parser(i, cb, allow_exceptions).parse(true, result);
         return result;
     }
 
@@ -12901,10 +12955,11 @@ class basic_json
                      std::random_access_iterator_tag,
                      typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
     static basic_json parse(IteratorType first, IteratorType last,
-                            const parser_callback_t cb = nullptr)
+                            const parser_callback_t cb = nullptr,
+                            const bool allow_exceptions = true)
     {
         basic_json result;
-        parser(detail::input_adapter(first, last), cb).parse(true, result);
+        parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);
         return result;
     }
 
diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp
index f23d2c18..f5415552 100644
--- a/test/src/unit-class_parser.cpp
+++ b/test/src/unit-class_parser.cpp
@@ -41,12 +41,31 @@ json parser_helper(const std::string& s)
 {
     json j;
     json::parser(nlohmann::detail::input_adapter(s)).parse(true, j);
+
+    // if this line was reached, no exception ocurred
+    // -> check if result is the same without exceptions
+    json j_nothrow;
+    CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr, false).parse(true, j_nothrow));
+    CHECK(j_nothrow == j);
+
     return j;
 }
 
 bool accept_helper(const std::string& s)
 {
-    return json::parser(nlohmann::detail::input_adapter(s)).accept(true);
+    // 1. parse s without exceptions
+    json j;
+    CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr, false).parse(true, j));
+    const bool ok_noexcept = not j.is_discarded();
+
+    // 2. accept s
+    const bool ok_accept = json::parser(nlohmann::detail::input_adapter(s)).accept(true);
+
+    // 3. check if both approaches come to the same result
+    CHECK(ok_noexcept == ok_accept);
+
+    // 4. return result
+    return ok_accept;
 }
 
 TEST_CASE("parser class")
@@ -590,8 +609,8 @@ TEST_CASE("parser class")
 
             SECTION("overflow")
             {
-                // overflows during parsing yield an exception, but is accepted anyway
-                CHECK(accept_helper("1.18973e+4932"));
+                // overflows during parsing
+                CHECK(not accept_helper("1.18973e+4932"));
             }
 
             SECTION("invalid numbers")
diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp
index 3de8f156..da406391 100644
--- a/test/src/unit-deserialization.cpp
+++ b/test/src/unit-deserialization.cpp
@@ -91,14 +91,19 @@ TEST_CASE("deserialization")
     {
         SECTION("stream")
         {
-            std::stringstream ss1, ss2, ss3;
+            std::stringstream ss1, ss2, ss3, ss4;
             ss1 << "[\"foo\",1,2,3,false,{\"one\":1}";
             ss2 << "[\"foo\",1,2,3,false,{\"one\":1}";
             ss3 << "[\"foo\",1,2,3,false,{\"one\":1}";
+            ss4 << "[\"foo\",1,2,3,false,{\"one\":1}";
             CHECK_THROWS_AS(json::parse(ss1), json::parse_error&);
             CHECK_THROWS_WITH(json::parse(ss2),
                               "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'");
             CHECK(not json::accept(ss3));
+
+            json j_error;
+            CHECK_NOTHROW(j_error = json::parse(ss1, nullptr, false));
+            CHECK(j_error.is_discarded());
         }
 
         SECTION("string")
@@ -108,6 +113,10 @@ TEST_CASE("deserialization")
             CHECK_THROWS_WITH(json::parse(s),
                               "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'");
             CHECK(not json::accept(s));
+
+            json j_error;
+            CHECK_NOTHROW(j_error = json::parse(s, nullptr, false));
+            CHECK(j_error.is_discarded());
         }
 
         SECTION("operator<<")
@@ -260,6 +269,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 2")
@@ -267,6 +280,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 3")
@@ -274,6 +291,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 4")
@@ -281,6 +302,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 5")
@@ -288,6 +313,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 0x7F, 0xC1};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 6")
@@ -295,6 +324,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 0x7F, 0xDF, 0x7F};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 7")
@@ -302,6 +335,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 0x7F, 0xDF, 0xC0};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 8")
@@ -309,6 +346,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 0x7F, 0xE0, 0x9F};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 9")
@@ -316,6 +357,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 0x7F, 0xEF, 0xC0};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 10")
@@ -323,6 +368,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 0x7F, 0xED, 0x7F};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 11")
@@ -330,6 +379,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 0x7F, 0xF0, 0x8F};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 12")
@@ -337,6 +390,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 0x7F, 0xF0, 0xC0};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 13")
@@ -344,6 +401,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 0x7F, 0xF3, 0x7F};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 14")
@@ -351,6 +412,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 0x7F, 0xF3, 0xC0};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 15")
@@ -358,6 +423,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'\"', 0x7F, 0xF4, 0x7F};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
 
             SECTION("case 16")
@@ -365,6 +434,10 @@ TEST_CASE("deserialization")
                 uint8_t v[] = {'{', '\"', '\"', ':', '1', '1'};
                 CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
                 CHECK(not json::accept(std::begin(v), std::end(v)));
+
+                json j_error;
+                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
+                CHECK(j_error.is_discarded());
             }
         }
     }