# How to interpret a 95% confidence interval (and what to write)

> A 95% confidence interval is the range of effect sizes compatible with your data under the model. Read it by asking which effects it makes implausible, then write the estimate with its interval.

Canonical: https://www.licklider.ai/guides/how-to-interpret-confidence-intervals/
Section: Guides › Interpreting results
Author: Licklider · Published 2026-11-10 · Last reviewed 2026-11-10 (UTC)

> **Quick answer.** A 95% confidence interval is the range of effect sizes that are compatible with your data, given the assumptions of the analysis; read the interval by asking which effects it makes implausible and whether those matter for your question. The "95%" describes the method: if the assumptions hold, 95% of intervals computed this way contain the true effect. It does not mean there is a 95% probability that this particular interval contains the true effect. Report the estimate with its interval, and compare groups with the interval for their difference, not by checking whether two group intervals overlap. For example: "The difference was 0.30 g (95% CI 0.09 to 0.51; Welch's t-test, t(358) = 2.85, p = 0.005)."

**Terms used below.** The *true effect* (or effect size) is the difference you would see with unlimited data; the *estimate* is the observed effect in your sample, such as a difference between group means. A *95% confidence interval (CI)* runs from a lower to an upper end around the estimate. For a symmetric interval, the *margin of error* is the distance from the estimate to either end. A *p-value* is the probability of data at least this extreme if there were no effect; *α* is the threshold you compare it with (usually 0.05); a two-sided 95% CI excludes zero exactly when the two-sided p from the same test is below 0.05. *df* (degrees of freedom) is the number printed in t(df), taken from the software output. The *null value* is the "no effect" value: 0 for a difference, 1 for a ratio. To *back-transform* is to turn a log-scale result back into a ratio. A *residual plot* shows each value minus its group mean, to spot skew or outliers. *Conservative* means the interval covers slightly more than its stated level. A difference "in SD units" is measured in standard deviations. *Adjusted* (simultaneous) intervals are widened for several comparisons; *unadjusted* intervals are not. A *prediction interval* is the range for a future single estimate or value. *Coverage* is the share of intervals, across many repeated experiments, that contain the true value. *Welch's t-test* compares two group means without assuming equal spreads; it is the default we use for two independent groups ([Welch vs Student](/guides/welch-vs-student-t-test/)). A *geometric mean* is the back-transformed mean of the log values; a *ratio of geometric means* is a fold change computed on the log scale. *Two-sided* means the interval leaves 2.5% at each end. *Nominal* coverage is the stated level (95%), as opposed to the coverage actually achieved. *Student's test* is the t-test that assumes equal spreads in both groups. An *equivalence analysis* asks whether an effect is small enough to ignore, using two one-sided tests against a pre-set margin.

## What "95%" means

Picture repeating the same experiment many times. Each repeat gives a different estimate and a different interval. If the analysis's assumptions hold, about 95% of those intervals contain the true effect and about 5% miss it. Any single interval either contains the true value or it does not; Greenland and colleagues put it bluntly: "A reported confidence interval is a range between two numbers. The frequency with which an observed interval (e.g., 0.72–2.88) contains the true effect is either 100 % if the true effect is within the interval or 0 % if not" ([Greenland et al. 2016](https://doi.org/10.1007/s10654-016-0149-3), misinterpretation 19).

![Fifty 95% confidence intervals from simulated repeats of one experiment; most cross the true difference of 1.0; five drawn in red miss it.](/guides/how-to-interpret-confidence-intervals/ci-coverage.svg)

The figure shows the first 50 of 10,000 simulated experiments with 6 mice per group and a true difference of 1.0 (in SD units). Five of the 50 intervals miss (more than the 2.5 expected by chance in a set this small; across all 10,000 runs, 4.7% missed). Across all runs the coverage was:

| Situation (6 mice per group unless stated) | Coverage of Welch's 95% CI |
| --- | --- |
| Normal data, assumptions hold | 95.3% (R: 95.3%) |
| Normal data, 3 mice per group | 96.6% (from a separate 200,000-run check, [coverage_check.py](/guides/how-to-interpret-confidence-intervals/coverage_check.py); Welch's interval is slightly conservative at this sample size) |
| Right-skewed data with very unequal spreads (log-scale SD 0.3 in one group, 1.0 in the other), analysed on the raw scale | 82.9% (R: 83.0%): in this simulation, Welch's nominal 95% CI covered 82.9% |

Two lessons follow. First, "95%" is a property of the procedure under its assumptions. Second, the label stays at 95% while the real coverage drops when the data break the model: here to 83%. Analyse skewed positive values on the log scale to keep the interval honest; that log-scale interval estimates the ratio of geometric means, not a raw difference in means, so report it as a fold change ([skewed data and other ANOVA problems](/guides/anova-assumptions-not-met/)). The seed was fixed before running; the simulation code is [example.py](/guides/how-to-interpret-confidence-intervals/example.py) and its R version [example.R](/guides/how-to-interpret-confidence-intervals/example.R).

**What to do:** write "95% CI" next to the interval and say what its two ends mean, for example: "The difference was 0.30 g (95% CI 0.09 to 0.51), so a difference larger than about half a gram is implausible under the model."

## Read it by asking which effects it makes implausible

An interval answers a better question than a yes-or-no significance verdict: which effects are still compatible with these data? Amrhein, Greenland and McShane recommend that authors "describe the practical implications of all values inside the interval, especially the observed effect (or point estimate) and the limits", remembering "that all the values between the interval's limits are reasonably compatible with the data, given the statistical assumptions used to compute the interval" ([Amrhein et al. 2019](https://doi.org/10.1038/d41586-019-00857-9)).

Three constructed results show how much this adds. A and B have almost the same p-value but say opposite things:

| Result | A: protein level, 6 mice per group | B: body weight, 180 mice per group | C: 5 mice per group |
| --- | --- | --- | --- |
| Estimate (95% CI) | 2.00-fold (1.28 to 3.12) | 0.30 g (0.09 to 0.51) | 1.5 units (−1.4 to 4.4) |
| Welch's t-test | t(10) = 3.46, p = 0.006 | t(358) = 2.85, p = 0.005 | t(8) = 1.19, p = 0.27 |
| Values the interval makes implausible | No change; any decrease; any increase larger than about 3.1-fold | No change; any change larger than about 0.5 g | Few: only values beyond a decrease of 1.4 or an increase of 4.4 |
| What to say | A large increase, estimated imprecisely: anything from about 1.3- to 3.1-fold fits | A real but small difference: at most about half a gram | Inconclusive; see [not significant](/guides/p-value-not-significant/) |

Values outside the interval are less compatible with the data, not refuted: the interval rests on the same assumptions as the test (Greenland et al. 2016, misinterpretation 20).

Width is the measure of precision. Greenland and colleagues contrast an interval from 5 to 40 (35 units wide) with one from −5 to 10 (15 wide): the second "includes the null value" but is "much more precise" (Greenland et al. 2016, misinterpretation 23). Compare widths only for the same outcome on the same scale; A, B and C use different units, so their widths cannot be ranked against each other.

**What to do:** in the Results, give the estimate and both ends of the interval; in the Discussion, say what the lower and the upper end would each mean for your question.

## Overlapping group intervals are not a test

Two group means can have overlapping 95% intervals and still differ clearly. Greenland and colleagues give an example where the intervals 1.04 to 4.96 and 4.16 to 19.84 overlap, "yet the test of the hypothesis of no difference in effect across studies gives P = 0.03" (Greenland et al. 2016, misinterpretation 21). The same happens in a simple constructed example. Each row below compares two independent groups of 10 mice with an SD of 2; each group's 95% interval has a margin of error of ±1.43:

| Difference between group means | Overlap of the two group intervals | Welch's t-test for the difference | 95% CI for the difference |
| --- | --- | --- | --- |
| 2.0 | 0.86 (60% of one margin of error) | p = 0.038 | 0.12 to 3.88 |
| 2.6 | 0.26 (18% of one margin of error) | p = 0.009 | 0.72 to 4.48 |
| 2.86 | intervals just touch | p = 0.005 | 0.98 to 4.74 |
| 3.5 | separated by 0.64 | p = 0.001 | 1.62 to 5.38 |

The comparison works in only one direction. If two 95% intervals for independent groups, computed under the same assumptions, are separated by a gap, the test of the difference gives p < 0.05; overlap does not imply p > 0.05, so if they overlap, compute the difference's own interval, because it can still exclude zero, as in the first two rows (Greenland et al. 2016, misinterpretation 21). Cumming and Finch propose "rules of eye" that "include guidelines for inferential interpretation of the overlap of CIs on independent group means" ([Cumming & Finch 2005](https://doi.org/10.1037/0003-066X.60.2.170), abstract). For paired or repeated measurements (the same animal before and after), the group intervals say nothing about the within-animal difference: compute each animal's difference and report its mean with the interval from a paired t-test, `stats.ttest_rel(after, before)` in Python or `t.test(after, before, paired = TRUE)` in R; that interval is for the mean within-animal difference ([paired vs unpaired](/guides/paired-vs-unpaired-t-test/)). For three or more groups, run the analysis for the whole design (for example a one-way ANOVA) and report the interval for each planned comparison, a comparison chosen before the data were seen ([how to report ANOVA](/guides/how-to-report-anova-results/)).

**What to do:** compute the interval for the difference itself (the last column) and report that; show group intervals in a figure only as a description of each group.

## Intervals for fold changes are asymmetric

For positive, right-skewed measurements such as concentrations, analyse the log values and back-transform: the estimate becomes a ratio of geometric means, and the back-transformed interval is an interval for that ratio, asymmetric on the raw scale. In result A, the log2 difference is 1.00 with 95% CI 0.36 to 1.64; back-transformed, that is a ratio of geometric means of 2.00 (95% CI 1.28 to 3.12). The interval extends 0.72 below and 1.12 above the estimate because the log scale treats halving and doubling as the same size of change ([statistics on fold change](/guides/statistics-on-fold-change/)).

The code below uses a second small example dataset, not result A, so its numbers differ. Paste it into a Python session with your own values (one value per mouse; average technical replicates per mouse first, see [what counts as n](/guides/what-counts-as-n/)):

```python
import numpy as np
from scipy import stats

control = np.array([1.02, 0.85, 1.20, 0.94, 1.10, 0.88])  # protein level, one value per mouse
treated = np.array([2.31, 1.62, 2.05, 1.48, 2.60, 1.95])

# Difference in original units (treated - control), Welch's 95% CI
res = stats.ttest_ind(treated, control, equal_var=False)
ci = res.confidence_interval(confidence_level=0.95)  # needs SciPy 1.11 or later
print(f"difference {treated.mean() - control.mean():.2f}, 95% CI {ci.low:.2f} to {ci.high:.2f}; "
      f"Welch t({res.df:.2f}) = {res.statistic:.2f}, p = {res.pvalue:.4f}")

# Ratio of geometric means: analyse log2 values, then back-transform the interval
lt, lc = np.log2(treated), np.log2(control)
res = stats.ttest_ind(lt, lc, equal_var=False)
ci = res.confidence_interval(confidence_level=0.95)
print(f"ratio {2 ** (lt.mean() - lc.mean()):.2f}, 95% CI {2 ** ci.low:.2f} to {2 ** ci.high:.2f}; "
      f"Welch t({res.df:.2f}) = {res.statistic:.2f}, p = {res.pvalue:.4f} (log scale)")
```

Or into R:

```r
control <- c(1.02, 0.85, 1.20, 0.94, 1.10, 0.88)  # protein level, one value per mouse
treated <- c(2.31, 1.62, 2.05, 1.48, 2.60, 1.95)

# Difference in original units (treated - control), Welch's 95% CI (R's t.test default)
d <- t.test(treated, control)
cat(sprintf("difference %.2f, 95%% CI %.2f to %.2f; Welch t(%.2f) = %.2f, p = %.4f\n",
            mean(treated) - mean(control), d$conf.int[1], d$conf.int[2],
            d$parameter, d$statistic, d$p.value))

# Ratio of geometric means: analyse log2 values, then back-transform the interval
r <- t.test(log2(treated), log2(control))
cat(sprintf("ratio %.2f, 95%% CI %.2f to %.2f; Welch t(%.2f) = %.2f, p = %.4f (log scale)\n",
            2^(mean(log2(treated)) - mean(log2(control))), 2^r$conf.int[1], 2^r$conf.int[2],
            r$parameter, r$statistic, r$p.value))
```

Both print a difference of 1.00 (95% CI 0.56 to 1.44; Welch t(6.03) = 5.59, p = 0.0014) and a ratio of 1.98 (95% CI 1.57 to 2.50; Welch t(8.43) = 6.70, p = 0.0001 on the log scale); each line gives every number its template below asks for. Decide before seeing the data whether you will analyse raw or log values, and report the one you planned. If the analysis has already been run and you had no plan, report the scale that matches how the outcome is usually reported in your field (differences in units for most measurements, fold changes for concentrations and expression), and say in the Methods that the scale was chosen after the data were seen. In GraphPad Prism, tick Welch's correction in the unpaired t test and copy the "95% CI of difference" row ([Welch vs Student](/guides/welch-vs-student-t-test/)).

## The interval is only as good as the unit and the model

The interval's width comes from the number of independent units. If you count cells from a few mice as if each cell were independent, the interval shrinks far below what the data support: on our [what counts as n](/guides/what-counts-as-n/) page, the same data give 0.64 to 1.82 with 60 cells as n and −0.58 to 3.05 with the 6 mice as n. Model the animal, or average per animal first ([nested data](/guides/nested-data-mixed-model/)).

The coverage table above shows the second requirement: the distributional assumptions. Choose the analysis from the design and the kind of data before you look at the results, and check residual plots for gross problems ([should you test for normality?](/guides/should-you-test-for-normality/)).

**What to do:** before reporting an interval, confirm that n is the number of independent animals or experiments and that the analysis matches the data's scale.

## 90%, 95% or 99%?

The level changes the width; the estimate stays the same. For result C (1.5 units, 5 mice per group):

| Level | Interval |
| --- | --- |
| 90% | −0.85 to 3.85 |
| 95% | −1.42 to 4.42 |
| 99% | −2.74 to 5.74 |

Use 95% by default, or the level your field or analysis plan specifies, and state it each time. A 90% interval matches a two-sided test at α = 0.10 or the two one-sided tests of an equivalence analysis at α = 0.05 ([not significant](/guides/p-value-not-significant/)); a one-sided bound matches a one-sided test ([one- vs two-tailed](/guides/one-vs-two-tailed-test/)). If several intervals are reported for a family of comparisons, say whether they are adjusted (simultaneous) or unadjusted ([which correction](/guides/which-multiple-comparison-correction/)).

**What to do:** pick the level in the analysis plan and write it next to every interval.

## What to write

Researchers find the probability wording hard: in a survey of 120 researchers and 442 students given six false statements about one interval, both groups "endorsed, on average, more than three statements" ([Hoekstra et al. 2014](https://doi.org/10.3758/s13423-013-0572-3), abstract). These substitutions keep the meaning:

| Avoid writing | Write instead | Why |
| --- | --- | --- |
| Avoid: "There is a 95% probability that the true difference lies between 0.09 and 0.51 g." | "The difference was 0.30 g (95% CI 0.09 to 0.51)." | The 95% describes the method, not this interval (Greenland et al. 2016, misinterpretation 19). |
| Avoid: "We are 95% confident the effect is real." | "Under the model's assumptions, the data are compatible with increases of 1.3- to 3.1-fold." | The interval describes a range of effect sizes, not the probability that an effect exists. |
| Avoid: "The groups did not differ: their error bars overlap." | "The difference was 2.0 units (95% CI 0.12 to 3.88; Welch's t-test, p = 0.038)." | Overlap is not a test; report the interval for the difference. |
| Avoid: "95% of future experiments will fall in this range." | Leave it out, or give a prediction interval computed for that purpose. | A 95% CI does not predict future estimates; even under ideal conditions, for two independent, equally precise studies the chance that the second study's estimate falls inside the first study's interval is 83% (Greenland et al. 2016, misinterpretation 22). |
| Avoid: "The interval excludes zero, so the estimate is precise." | "The interval is narrow (0.09 to 0.51 g), so the estimate is precise." | Precision is width, not whether zero is inside (Greenland et al. 2016, misinterpretation 23). |

Templates for a Results sentence, with every bracket replaced by your own values:

> [Outcome] was [higher / lower] in [group] than in [comparison group] (difference ([group] − [comparison group]) [estimate] [units], 95% CI [lower] to [upper]; Welch's t-test, t([df]) = [t], p = [p]; n = [animals] per group).

Keep the sign in the order written in the brackets, even when the sentence says "lower". A filled-in example from the code above: "Protein level was higher in treated than in control mice (difference (treated − control) 1.00 units, 95% CI 0.56 to 1.44; Welch's t-test, t(6.03) = 5.59, p = 0.0014; n = 6 mice per group)."

> [Outcome] was [ratio]-fold higher in [group] (ratio of geometric means, 95% CI [lower] to [upper]; Welch's t-test on log-transformed values, p = [p]; n = [animals] per group).

For the Methods, one sentence covers it: "Results are reported as estimates with two-sided 95% confidence intervals." Gardner and Altman made the same recommendation in 1986: "Confidence intervals, if appropriate to the type of study, should be used for major findings in both the main text of a paper and its abstract" ([Gardner & Altman 1986](https://doi.org/10.1136/bmj.292.6522.746), abstract).

If a reviewer asks you to interpret an interval, a reply in the same form works: "We now report the difference with its 95% confidence interval ([estimate], 95% CI [lower] to [upper]) and describe what the lower and upper limits would mean for [question] (Results, [page/line])."

**What to do:** copy the template, replace every bracket, and check the wording against the table before you submit.

## Check what an AI assistant wrote

Assistants reproduce the common misreadings. Before you use an interval or its description:

1. **Does the text say "95% probability" about this interval?** Replace it with the estimate-and-limits wording above.
2. **Is a group comparison based on overlapping error bars?** Ask for the interval of the difference.
3. **Which test produced the interval?** In SciPy, `ttest_ind` uses Student's test unless `equal_var=False`; R's `t.test` uses Welch's test by default.
4. **Is n the number of animals?** If the code passed one row per cell or well, the interval is too narrow.
5. **Was a ratio analysed on the log scale?** An interval for a fold change should be asymmetric on the raw scale.

**What to do:** run the five checks, and paste the code's actual output, not the assistant's summary, into your notes.

## References

- Amrhein V, Greenland S, McShane B (2019). Scientists rise up against statistical significance. *Nature* 567:305–307. [doi:10.1038/d41586-019-00857-9](https://doi.org/10.1038/d41586-019-00857-9)
- Cumming G, Finch S (2005). Inference by eye: confidence intervals and how to read pictures of data. *American Psychologist* 60:170–180. [doi:10.1037/0003-066X.60.2.170](https://doi.org/10.1037/0003-066X.60.2.170) (cited from the abstract)
- Gardner MJ, Altman DG (1986). Confidence intervals rather than P values: estimation rather than hypothesis testing. *BMJ* 292:746–750. [doi:10.1136/bmj.292.6522.746](https://doi.org/10.1136/bmj.292.6522.746) (cited from the abstract)
- Greenland S, Senn SJ, Rothman KJ, Carlin JB, Poole C, Goodman SN, Altman DG (2016). Statistical tests, P values, confidence intervals, and power: a guide to misinterpretations. *European Journal of Epidemiology* 31:337–350. [doi:10.1007/s10654-016-0149-3](https://doi.org/10.1007/s10654-016-0149-3)
- Hoekstra R, Morey RD, Rouder JN, Wagenmakers E-J (2014). Robust misinterpretation of confidence intervals. *Psychonomic Bulletin & Review* 21:1157–1164. [doi:10.3758/s13423-013-0572-3](https://doi.org/10.3758/s13423-013-0572-3) (cited from the abstract)

## Related

- [p = 0.06 or “not significant”: what it means](https://www.licklider.ai/guides/p-value-not-significant/)
- [Reviewer asks for effect sizes](https://www.licklider.ai/guides/reviewer-asks-for-effect-sizes/)
- [How to report a t-test](https://www.licklider.ai/guides/how-to-report-a-t-test/)
- [What counts as n?](https://www.licklider.ai/guides/what-counts-as-n/)

## How this page was made

- Written and published by Licklider. Statements about interpretation cite peer-reviewed papers listed under References; quoted wording was checked against the source text, and a source read only as an abstract is cited at that level.
- All examples are constructed. Their numbers, the coverage simulation and the figure were produced by stored code (Python 3.13 with SciPy 1.18.1; R 4.3.3); the worked-example numbers agree to every printed digit in both languages, and the coverage rates differ only by simulation error.
- Separate review passes checked the statistics, the citations and readability before publication.
