Quick answer
Use creep.withdraw(container, RESOURCE_ENERGY) to move Energy from a Container into a Creep. First confirm that the Creep has free Store capacity and that the Container currently holds Energy. If the method returns ERR_NOT_IN_RANGE, move toward the Container and retry on a later tick. Save every return value so withdrawal and movement failures remain distinguishable.
withdraw() and transfer() use opposite directions
| Call | Resource direction |
|---|---|
creep.withdraw(container, RESOURCE_ENERGY) | Container → Creep |
creep.transfer(spawn, RESOURCE_ENERGY) | Creep → Spawn |
Use the delivery tutorial when the Creep already carries Energy. This article only handles acquisition from one Container.
Prerequisites and read-only checks
The example expects a Creep named Hauler1 with active CARRY and MOVE parts. Run this read-only Console check before changing the main loop:
const creep = Game.creeps.Hauler1;
console.log(JSON.stringify({
creepFound: Boolean(creep),
spawning: creep ? creep.spawning : null,
activeCarry: creep ? creep.getActiveBodyparts(CARRY) : null,
activeMove: creep ? creep.getActiveBodyparts(MOVE) : null,
freeEnergyCapacity: creep
? creep.store.getFreeCapacity(RESOURCE_ENERGY)
: null
}));
A body may contain a CARRY part while having no active CARRY ability after damage. The complete script checks active parts and Store capacity separately. Review WORK, CARRY, and MOVE when either value is unexpected.
Find a Container that currently has Energy
function findContainerWithEnergy(creep) {
return creep.pos.findClosestByPath(
FIND_STRUCTURES,
{
filter: structure =>
structure.structureType === STRUCTURE_CONTAINER
&& structure.store.getUsedCapacity(
RESOURCE_ENERGY
) > 0
}
);
}
The result can be null. A room may contain no Container, every Container may be empty, or no valid path may be available. Do not pass a missing result into withdraw().
Complete focused example
State impact: this script may move Hauler1 and withdraw Energy from one Container. It does not deliver the Energy afterward and does not write Memory.
function findContainerWithEnergy(creep) {
return creep.pos.findClosestByPath(
FIND_STRUCTURES,
{
filter: structure =>
structure.structureType === STRUCTURE_CONTAINER
&& structure.store.getUsedCapacity(
RESOURCE_ENERGY
) > 0
}
);
}
module.exports.loop = function () {
const creep = Game.creeps.Hauler1;
if (!creep) {
console.log('Hauler1 was not found.');
return;
}
if (creep.spawning) {
return;
}
if (creep.getActiveBodyparts(CARRY) <= 0) {
console.log('Hauler1 has no active CARRY part.');
return;
}
const freeCapacity =
creep.store.getFreeCapacity(RESOURCE_ENERGY);
if (freeCapacity === null || freeCapacity <= 0) {
return;
}
const container = findContainerWithEnergy(creep);
if (!container) {
console.log(
'No reachable Container with Energy was found.'
);
return;
}
const withdrawResult = creep.withdraw(
container,
RESOURCE_ENERGY
);
if (withdrawResult === ERR_NOT_IN_RANGE) {
const moveResult = creep.moveTo(container, {
range: 1,
reusePath: 5
});
if (
moveResult !== OK
&& moveResult !== ERR_TIRED
) {
console.log(
'Hauler1 moveTo() returned '
+ moveResult
);
}
return;
}
if (withdrawResult !== OK) {
console.log(
'Hauler1 withdraw() returned '
+ withdrawResult
);
}
};
The target is selected again on later ticks. Its Store can change because another Creep withdraws first, so the filter does not remove the need to inspect the actual API result.
Return-code troubleshooting
| Result | Meaning | Action |
|---|---|---|
OK | The command was accepted for this tick. | Inspect both Stores on a later tick. |
ERR_NOT_IN_RANGE | The target is not adjacent. | Move toward it and retry later. |
ERR_NOT_ENOUGH_RESOURCES | The target lacks the requested resource amount. | Refresh target and Store data. |
ERR_FULL | The Creep has no free capacity. | Switch to a delivery task. |
ERR_INVALID_TARGET | The object cannot be used as a withdrawal target. | Check existence and target type. |
ERR_BUSY | The Creep is still spawning. | Wait until spawning finishes. |
ERR_INVALID_ARGS | The resource type or amount is invalid. | Inspect the arguments. |
Use the English Screeps error-code reference when movement or a less common result needs separate diagnosis.
Verify Store changes on a later tick
Official debugging guidance notes that an accepted command is not the same as a verified final state. Record a before snapshot, submit the action, then inspect the next tick:
console.log(JSON.stringify({
tick: Game.time,
creepEnergy:
creep.store.getUsedCapacity(RESOURCE_ENERGY),
containerEnergy:
container.store.getUsedCapacity(RESOURCE_ENERGY)
}));
Do not assume that the filtered amount remains unchanged. Another Creep may compete for the same Container during the tick.
Why this guide does not use working state
A working flag is useful when one Creep alternates between acquisition and delivery, but it is not an argument to withdraw(). This guide isolates target selection, capacity checks, action submission, range handling, and return-code logging. Add cross-tick task switching only after the single withdrawal works. See Screeps Memory basics.
Debugging checklist
- Confirm the Creep name and capitalization.
- Wait until the Creep finishes spawning.
- Check for at least one active CARRY part.
- Check free Store capacity before calling
withdraw(). - Filter for
STRUCTURE_CONTAINERand positive Energy. - Handle a missing or unreachable target.
- Save
withdrawResultandmoveResultseparately. - Retry the action on later ticks instead of expecting one call to finish the trip.
- Verify Creep and Container Store changes after the command.
Scope and next steps
This example does not choose among Containers by logistics priority, reserve targets for multiple haulers, withdraw from Storage, Tombstones, or Ruins, construct Containers, or decide where the Energy should be delivered. Continue with picking up dropped Energy to learn the separate API for ground resources.
Frequently asked questions
What direction does withdraw() move Energy?
It moves Energy from the target Container into the calling Creep.
Why does withdraw() return ERR_NOT_IN_RANGE?
The Creep must be adjacent. Move toward the target and retry on a later tick.
Why does withdraw() return ERR_FULL?
The Creep has no free Store capacity for the selected resource.
Does OK prove that Energy arrived?
No. It proves that the API accepted the command. Confirm the Store values after tick processing.