Quantum teleportation moves the exact state of a qubit from one place to another without physically transporting the qubit itself. The protocol takes three qubits, one shared entangled pair, and two classical bits, and you build the whole thing in under thirty lines of Qiskit.
The name causes most of the confusion around this protocol, so let's clear this up before touching any code.
What Teleportation Is Not
The protocol does not move matter. Nothing about the qubit's physical particle relocates anywhere. What moves is information: the receiver's qubit ends the protocol in exactly the quantum state the sender's qubit started in.
The protocol does not allow faster-than-light communication. The receiver's qubit is unusable garbage until two classical bits arrive from the sender, and this transmission is bounded by the speed of light like any other classical signal. Nature is careful here: entanglement alone correlates outcomes, and never carries a controllable signal on its own.
The protocol does not copy the qubit either. The no-cloning theorem forbids a perfect copy of an unknown quantum state from ever existing alongside the original, and teleportation respects this strictly: the act of transmitting the state destroys the sender's copy. At the end there is exactly one qubit holding the state, and the receiver's qubit isn't the one you started with.
The Protocol in Three Moves
- Share entanglement in advance. Sender and receiver each hold one half of a Bell pair, distributed before anyone knows what state needs teleporting.
- The sender performs a joint (Bell-basis) measurement on their half of the pair together with the qubit to be teleported. This produces one of four random two-bit outcomes and destroys the original qubit's state as a side effect.
- The sender sends those two classical bits to the receiver, who applies one of four corresponding gates (identity, X, Z, or XZ) to their half of the pair. This correction reconstructs the exact original state, regardless of which of the four random outcomes came up in step 2.
The randomness in step 2 is real and unavoidable, and the correction in step 3 cancels this out deterministically. This cancellation is the entire point of the protocol, and this step is also the easiest part to get wrong, more on this below.
Building the Circuit in Qiskit
Three qubits: q0 holds the state to teleport, q1 is the sender's half of the entangled pair, q2 is the receiver's half.
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, transpile
from qiskit_aer import AerSimulator
theta = 0.9 # arbitrary angle, stands in for "an unknown state"
qr = QuantumRegister(3, "q")
cr = ClassicalRegister(2, "c")
result_reg = ClassicalRegister(1, "result")
qc = QuantumCircuit(qr, cr, result_reg)
# Step 0: prepare the state to teleport on q0. In a real protocol
# this state is unknown. Ry(theta) here only gives us something
# concrete to verify against later.
qc.ry(theta, 0)
qc.barrier()
Step 1: Distribute the Entangled Pair
qc.h(1)
qc.cx(1, 2)
qc.barrier()
Standard Bell state construction: a Hadamard followed by a CNOT. q1 and q2 are now maximally entangled, and in a real installation they'd already be separated: q1 with the sender, q2 with the receiver, before the rest of the protocol runs.
Step 2: Bell-Basis Measurement
qc.cx(0, 1)
qc.h(0)
qc.measure(0, cr[0])
qc.measure(1, cr[1])
qc.barrier()
The CNOT and Hadamard rotate the joint state of q0 and q1 into the Bell basis, so a standard computational-basis measurement now reads out which of the four Bell states the pair collapsed into. This outcome is uniformly random, roughly 25% for each of the four combinations of cr[0] and cr[1], and correcting for this randomness is exactly what the next step does.
Step 3: Classically-Controlled Correction
with qc.if_test((cr[1], 1)):
qc.x(2)
with qc.if_test((cr[0], 1)):
qc.z(2)
This is a genuine mid-circuit classical condition, not a shortcut: q2 only gets an X gate when the classical bit cr[1] measured 1, and only gets a Z gate when cr[0] measured 1. Qiskit's if_test context manager compiles this into a real dynamic circuit, the same mechanism a physical deployment would use to send two classical bits over an ordinary channel and apply a correction on the other end.
Step 4: Verify the Protocol Worked
qc.ry(-theta, 2)
qc.measure(2, result_reg[0])
sim = AerSimulator()
tqc = transpile(qc, sim)
counts = sim.run(tqc, shots=4096).result().get_counts()
print(sorted(counts.items()))
The verification trick: apply the inverse of the original rotation to q2 and measure the qubit. If q2 ended up in the exact state q0 started in, undoing this rotation sends the qubit back to |0⟩, and the result bit reads 0. The four (cr[0], cr[1]) outcomes stay roughly evenly split across the run, the random Bell-measurement outcome behaving as expected, while the result bit reads 0 regardless of which of the four outcomes occurred. This is the payoff: the correction step cancels whichever random outcome came up, every single time, not only on average.
The Mistake: Skipping the Correction "Because the Circuit Is Fine Anyway"
Looking at this circuit, one might assume the correction step is a minor detail, since three of the four Bell outcomes seem close to the identity case. They aren't. Skip the if_test blocks and measure q2 directly: the result comes back correct only for the roughly 25% of runs where the Bell measurement happened to land on |00⟩, and comes back scrambled the other three quarters of the time. There's no partial credit here. The correction isn't an optimization, the correction is the mechanism making the protocol deterministic instead of a quarter-reliable coin flip.
What Teleportation Is For
The protocol itself has no independent application as a standalone party trick. Its importance is structural: this is the mechanism quantum networks and distributed quantum computing use to move a qubit's state between nodes connected only by pre-shared entanglement and a classical link, rather than by a direct quantum wire. Every proposal for linking separate QPUs into one larger logical machine, or for quantum repeaters extending entanglement across long fiber links, builds on exactly this primitive. Superdense coding, which sends two classical bits using one transmitted qubit, is the same idea run in reverse.
Running This on Real Hardware
Mid-circuit measurement followed by a classically-conditioned gate is a genuinely harder hardware requirement than a static circuit. The system needs fast, low-latency classical control electronics, which read out a measurement and feed a correction back into the same circuit before the qubits decohere, a capability often called "dynamic circuits" and one not every cloud backend supports on every device generation. Where dynamic circuits aren't available, some implementations substitute conditioned two-qubit gates for the classical corrections and defer all measurement to the end, which verifies the protocol's math correctly in simulation but sidesteps the actual classical-communication step, which makes teleportation practical for networking in the first place. For real hardware runs, check whether your target backend explicitly supports dynamic circuits before assuming this code runs as written.
Next Steps
- Qiskit SDK guide: full setup, backends, and dynamic-circuits support
- Quantum networking and distributed computing: where teleportation fits into linking separate QPUs
- Glossary: entanglement, Bell state, superdense coding, and the rest of the vocabulary