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
- Define the function:
f = lambda x: x**2. - Call
y, abserr = quad(f, 0, 4). - 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.
- SciPy reference: scipy.integrate.quad (checked 2026-10-29)
- SciPy tutorial: Integration (scipy.integrate) (checked 2026-10-29)
- SciPy: Installing SciPy (checked 2026-10-29)







