Skip to main content
v2026.11,986 entries · CC-BY 4.0

NumPy Cross Product: np.cross and np.linalg.cross

How to compute a cross product in NumPy with np.cross and np.linalg.cross, including axis arguments, output sign, the 2-D deprecation and common errors.

Written and maintained by CASRAI Editorial Board

Published · Last updated

On this page

numpy.cross(a, b) returns the cross product of two vectors, or of many vectors at once: for 3-element vectors it gives a new vector perpendicular to both inputs. Since NumPy 2.0 there are two functions for this, np.cross and np.linalg.cross. They return the same numbers for 3-element input and differ in what else they accept, which is the choice this guide helps you make.

What it is used for in research

The NumPy manual defines the cross product of a and b in R3 as “a vector perpendicular to both a and b”. In analysis code that means computing surface normals from two edge vectors, finding the axis perpendicular to a plane spanned by two measured directions, or checking whether two direction vectors are parallel (the result is the zero vector). If a and b are arrays of vectors, one call computes every cross product in the batch, with full broadcasting of the inputs.

Install or access

NumPy’s install page gives these routes. With pip: pip install numpy. With conda, inside an activated environment: conda install numpy. To keep it isolated, create a virtual environment first with python -m venv my-env, activate it (source my-env/bin/activate on macOS and Linux, my-env\Scripts\activate on Windows), then run pip install numpy. Import it with import numpy as np and check the installed version with print(np.__version__). If the import fails, NumPy maintains an ImportError troubleshooting page at https://numpy.org/doc/stable/user/troubleshooting-importerror.html.

Step-by-step: compute a cross product

  1. Import NumPy. import numpy as np
  2. Call the function on two 3-element vectors. np.cross([1, 2, 3], [4, 5, 6]) returns array([-3, 6, -3]).
  3. Batch several pairs. By default the vectors lie along the last axis. x = np.array([[1, 2, 3], [4, 5, 6]]) and y = np.array([[4, 5, 6], [1, 2, 3]]) give np.cross(x, y) equal to array([[-3, 6, -3], [ 3, -6, 3]]): one result row per input row.
  4. Change where the vectors sit with the axis arguments. The signature is numpy.cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None). axisa and axisb say which axis of a and b holds the vector, axisc says which axis of the result holds it, and axis, if given, overrides all three.

Why axisa and axisb change the answer

With the NumPy manual’s 3 by 3 example, x = [[1,2,3],[4,5,6],[7,8,9]] and y = [[7,8,9],[4,5,6],[1,2,3]], the default call treats each row as a vector and returns [[-6, 12, -6], [0, 0, 0], [6, -12, 6]]. The middle row is zero because the two middle rows are identical, so those vectors are parallel. Calling np.cross(x, y, axisa=0, axisb=0) treats each column as a vector instead and returns [[-24, 48, -24], [-30, 60, -30], [-36, 72, -36]]. Same data, different vectors, different answer; when a result looks wrong, check which axis holds your vectors first.

Output and how to read it

The function returns an ndarray. The result is perpendicular to both inputs, and its direction follows the right-hand rule. Order matters: swapping the arguments negates the result. In the examples above, np.cross([1,2,3],[4,5,6]) gives [-3, 6, -3] while np.cross([4,5,6],[1,2,3]) gives [3, -6, 3]. This is also visible in the 2 by 3 batch example, where the second row is the negative of the first because the two input rows are swapped. Parallel vectors, including a vector crossed with itself, return all zeros. To move the result’s vector axis, set axisc: with axisc=0 the 2 by 3 batch result comes back transposed, as a 3 by 2 array [[-3, 3], [6, -6], [-3, 3]]. For reshaping like that in general, see the guide to NumPy transpose.

Troubleshooting

Why does np.cross raise ValueError?

The manual states that numpy.cross raises ValueError when the dimension of the vector axis in a or b is not 3. A 4-element input fails this check. Check the shape with a.shape and make sure the length-3 axis is the one axisa, axisb or axis points at. If your vectors sit in columns, pass axisa=0, axisb=0 as shown above.

What about 2-element vectors?

The NumPy 2.0.0 release notes list under deprecations: “Arrays of 2-dimensional vectors for np.cross have been deprecated. Use arrays of 3-dimensional vectors instead.” Code that crosses 2-element vectors should be moved to 3-element vectors, for example by adding a zero third component.

Why do shapes not line up?

The function supports full broadcasting of its inputs, so a single vector can be crossed with a whole batch. Shapes that cannot broadcast raise an error. The guide to broadcasting in NumPy explains the rules, and NumPy ndarray length helps when you need to inspect dimensions.

Free alternatives

Both functions below ship with NumPy, which is free and open source.

Function Signature What the manual says
numpy.cross cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None) Cross product of two (arrays of) vectors; vector axes default to the last axis and must have 3 dimensions.
numpy.linalg.cross cross(x1, x2, /, *, axis=-1) Cross product of 3-element vectors; if inputs are multi-dimensional, each pair of corresponding 3-element vectors is computed independently. Array API compatible.

np.cross vs np.linalg.cross

The 2.0.0 release notes say numpy.linalg.cross “differs from numpy.cross by accepting three-dimensional vectors only” and is compatible with the array API standard. The manual’s own example gives the same answer from both: np.linalg.cross([1,2,3],[4,5,6]) returns array([-3, 6, -3]). The practical differences are the signature (x1 and x2 are positional-only, axis is keyword-only, and there are no separate axisa, axisb, axisc) and scope. Choose np.linalg.cross when you want code that follows the array API standard and only ever handles 3-element vectors; choose np.cross when you need independent control of the input and output axes. For a column layout, np.linalg.cross(x, y, axis=0) on x = [[1,2],[3,4],[5,6]] and y = [[4,5],[6,1],[2,3]] returns [[-24, 6], [18, 24], [-6, -18]] in the manual. Related functions listed in the manual are inner and outer. For other NumPy numerical routines, see NumPy power and NumPy standard deviation.

FAQ

What does np.cross return?

An ndarray holding the cross product: a vector perpendicular to both inputs, or an array of such vectors when the inputs are arrays of vectors.

Does the order of the arguments matter?

Yes. Swapping them negates the result, as in [-3, 6, -3] versus [3, -6, 3].

Can I use np.cross on 2-D vectors?

That use was deprecated in NumPy 2.0, per the release notes quoted above. Use 3-element vectors.

Which function should I use in new code?

Both work for 3-element vectors. See the comparison above: np.linalg.cross is the 3-only, array API compatible version added in NumPy 2.0.

Sources

  • NumPy manual, numpy.cross: https://numpy.org/doc/stable/reference/generated/numpy.cross.html (checked 2026-10-29)
  • NumPy manual, numpy.linalg.cross: https://numpy.org/doc/stable/reference/generated/numpy.linalg.cross.html (checked 2026-10-29)
  • NumPy 2.0.0 release notes: https://numpy.org/doc/stable/release/2.0.0-notes.html (checked 2026-10-29)
  • NumPy installation: https://numpy.org/install/ (checked 2026-10-29)

Follow CASRAI

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

Ask CASRAI · free to try

Ask about NumPy Cross Product: np.cross and np.linalg.cross

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 →