Skip to main content
v2026.11,858 entries · CC-BY 4.0
LAC HealthMedical & Research SuppliesReagents, PPE & instruments — chain-of-custody documented.Fast, traceable sourcing built for regulated research environments, from bench consumables to instrumentation.Shop lac.us CodeCASRAIlac.us

scipy.integrate.quad: Syntax, Error Estimate and Failures

How scipy.integrate.quad works: signature, infinite limits, args, reading abserr, and the documented case where a tiny error estimate hides a wrong result.

Written and maintained by CASRAI Editorial Board

Last updated

scipy.integrate.quad computes a definite integral of a function of one variable between two limits and returns two numbers: the estimated integral and an estimate of its absolute error. This guide covers the call signature, a worked example for each common case, and how to read the error estimate, including a documented case where the answer is wrong while the error estimate is tiny.

What quad is used for in research

The SciPy tutorial describes quad as the function “provided to integrate a function of one variable between two points.” In research code that usually means integrating a density or a response function that has no closed-form antiderivative: normalising a probability density, computing an expected value, or accumulating a rate over time. quad calls the QUADPACK Fortran library, and the integral must converge for the result to be valid.

If you instead have measurements at discrete points rather than a function, quad is the wrong tool; see the alternatives table below. For fitting a model to data rather than integrating it, see our guide to curve_fit in SciPy and SciPy least_squares.

Install or access

SciPy’s installation page (scipy.org/install) gives two routes. In a virtual environment, run python -m pip install scipy. With conda or mamba, run conda install scipy or mamba install scipy (conda-forge). The function is then imported with:

from scipy.integrate import quad
import numpy as np

Step-by-step: integrating a function with quad

Syntax

The documented signature is:

quad(func, a, b, args=(), full_output=0, epsabs=1.49e-08, epsrel=1.49e-08,
     limit=50, points=None, weight=None, wvar=None, wopts=None,
     maxp1=50, limlst=50, complex_func=False)

func is integrated along its first argument, from a to b. Use -numpy.inf or numpy.inf for an infinite limit.

Step 1: a finite interval

  1. Define the function: f = lambda x: x**2.
  2. Call y, abserr = quad(f, 0, 4).
  3. The reference page shows the result (21.333333333333332, 2.3684757858670003e-13). The analytic answer is 64/3, so the first value matches and the second is the estimated absolute error.

Step 2: an infinite limit

Pass np.inf as the upper limit: quad(lambda x: np.exp(-x), 0, np.inf) returns (1.0, 5.842605999138044e-11) in the reference page. For infinite limits SciPy transforms the range to (0, 1), and any optional outputs then refer to the transformed range.

Step 3: extra parameters with args

To pass constants into the function, make them extra positional arguments and supply them as a tuple in args. With f = lambda x, a: a*x, quad(f, 0, 1, args=(1,)) gives an integral of 0.5 and args=(3,) gives 1.5. The tuple form is needed even for one value: (3,), not 3.

Step 4: known trouble spots with points

If the integrand has a singularity or discontinuity inside the interval, pass its location in points, for example points=[0.5]. The values need not be sorted. Per the reference page, points cannot be combined with weight.

Step 5: oscillatory and weighted integrands

The weight argument accepts 'cos', 'sin', 'alg', 'alg-loga', 'alg-logb', 'alg-log' and 'cauchy'. These select specialised QUADPACK routines; the table in the next section shows which.

Step 6: complex-valued functions

Set complex_func=True. The reference page states that the real and imaginary parts are then integrated separately.

Which QUADPACK routine runs

The reference page maps the arguments you give to the underlying routine:

You pass Routine used Behaviour documented
Finite limits, no weight, no points qagse 21-point Gauss-Kronrod rule on each subinterval, with adaptive subdivision
An infinite limit qagie Range transformed to (0, 1)
points qagpe Break points for singularities or discontinuities
weight='sin' or 'cos', finite limits qawoe Oscillatory weight
weight='sin' or 'cos', infinite limit qawfe Oscillatory weight, infinite range
weight='alg' and the alg-log* options qawse Algebraic and logarithmic end-point weights
weight='cauchy' qawce Cauchy principal value

Output and how to read it

quad returns y, the integral, and abserr, an estimate of the absolute error. The target it works to is abs(i - result) <= max(epsabs, epsrel*abs(i)), where i is the true integral; both tolerances default to 1.49e-08. The limit argument (default 50) is an upper bound on the number of subintervals.

With full_output set to a nonzero value, quad also returns infodict and message. The infodict keys are neval, last, alist, blist, rlist, elist and iord. Setting full_output also suppresses warning messages, so do not set it just to silence a warning you have not understood.

A small error estimate is not a guarantee

The reference page includes an example that shows the limits of abserr. The function is y = lambda x: 1 if x <= 0 else 0, whose integral over [-1, 1] is 1:

Call Result (y, abserr)
quad(y, -1, 1) (1.0, 1.1102230246251565e-14)
quad(y, -1, 100) (1.0000000002199108, 1.0189464580163188e-08)
quad(y, -1, 10000) (0.0, 0.0)

In the third call the true integral is still 1, yet quad reports 0.0 with an error estimate of 0.0. The estimate describes what the routine sampled, not what it missed. The SciPy tutorial shows the same effect with a Gaussian: integrating over [-10000, 10000] returns about 2e-203, missing the peak, while [-15, 15] returns about 1.7725. The tutorial’s advice is to use “integration limits that tightly surround the important part of the integrand.”

Troubleshooting

The integral is zero or far too small

The limits are probably much wider than the region where the integrand is non-negligible. Narrow them to surround the important part of the integrand, as the tutorial’s [-15, 15] Gaussian example does.

The integrand has a jump or singularity

Pass its location in points. The documented sharp-feature example shows how the result degrades as the interval grows around a discontinuity.

The integral does not converge

The reference page states that the integral must converge for valid results. Check the integrand’s behaviour at the limits before trusting any returned value.

You need to see what the routine did

Call with full_output=1 and inspect infodict (for example neval, the number of function evaluations) and message. Remember that this also suppresses warnings.

The function takes extra parameters

Use args=(...) as in Step 3 rather than rebuilding the lambda in a loop.

Free alternatives and neighbours in SciPy

All of these are part of SciPy itself and are described in the SciPy integration tutorial.

Situation Use What the tutorial says
Function of two variables dblquad Double integral
Function of three variables tplquad Triple integral
Any number of variables nquad Bounds given as a list ordered innermost to outermost; the tutorial’s nested example gives 1/96
Equally spaced samples, 2k+1 points romb Romberg integration of sampled data
Sampled data, arbitrary spacing trapezoid, simpson Simpson’s rule is exact for cubics on an odd number of equally spaced samples

For related numerical work in SciPy, see our guides to SciPy interpolation and the NumPy Fourier transform.

FAQ

What does scipy.integrate.quad return?

A tuple of the integral estimate and an estimate of the absolute error. With full_output nonzero it also returns infodict and a message.

How do I integrate to infinity with quad?

Pass np.inf (or -np.inf) as the limit. For example, quad(lambda x: np.exp(-x), 0, np.inf) returns (1.0, 5.842605999138044e-11).

How do I pass extra arguments to the function?

Put them after the integration variable in the function definition and supply them as a tuple in args.

What are the default tolerances?

Both epsabs and epsrel default to 1.49e-08, and limit defaults to 50 subintervals.

Can I use quad on data points instead of a function?

No. For sampled data use trapezoid, simpson or, for 2k+1 equally spaced points, romb.

Sources

Official documentation, checked 2026-10-29.

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about scipy.integrate.quad: Syntax, Error Estimate and Failures

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →