How One Developer Automated His Way to Every Limited Sneaker Drop

Ever tried to cop limited Jordans on release day?

If you have, you know the pain. Refresh the website — sold out in seconds. Drive to the store — lines around the block at 5 AM. Call the store — busy signal for hours.

In 2022, one developer said "screw this" and built a system that guaranteed him every pair he wanted.

Here's how he did it — and why it's a masterclass in solving real problems with code.

The Problem: Footlocker's "Call & Collect" Was a Nightmare

In 2022, Footlocker rolled out a new release method globally: Call & Collect.

The concept was simple:

  • Limited drops happen on pre-set days
  • You call your local store
  • Reserve your pair over the phone
  • Pick it up in-store later

Sounds fair, right? Wrong.

On release days for limited Jordan 1s or 4s, stores would get hundreds — sometimes thousands — of calls. Getting through was like winning the lottery. Most people spent hours hitting redial, only to hear "sorry, we're sold out" when they finally connected.

But where others saw frustration, this developer saw opportunity.

The Solution: Turn One Call Into 50

Instead of competing with everyone else hitting redial, he built a script that turned him into a one-man call center.

Here's the genius part:

He created a conference call system where:

  1. His personal phone joins a conference room and waits
  2. The script launches 50 simultaneous calls to Footlocker from different numbers
  3. When Footlocker picks up any call, they're automatically added to his conference
  4. He switches between voices (and his girlfriend) to reserve multiple pairs
  5. When they hang up, the script immediately calls them back

Think about that. While everyone else is hitting redial, he's making 50 calls at once. And when the store hangs up on one "customer," that same "customer" is calling back instantly.

It's not even a competition anymore.

The Setup: Everything You Need to Dominate

Before diving into the code, here's what made this possible:

1. Twilio Account

  • Provides programmable phone numbers
  • Handles the calling infrastructure
  • Costs about $1 per number per month

2. Phone Numbers

  • He rented 20 numbers across different area codes
  • Mixed local and non-local numbers to seem legitimate
  • Total cost: ~$20/month

3. Node.js Environment

  • Simple JavaScript runtime
  • Required packages: twilio, chalk (for pretty logs), moment (for timestamps)

Here's the initial setup:

const accountSid = "_"; // Your Twilio account SID
const authToken = "_";  // Your Twilio auth token
const client = require("twilio")(accountSid, authToken);
const chalk = require("chalk");
const moment = require("moment");
const fs = require("fs");

// Pretty logging with timestamps
function log(message) {
  console.log(`[${moment().format("h:mm:ss:SSS")}] ${message}`);
}

Simple setup, but notice the attention to detail. Even the logging is optimized — millisecond timestamps let him track exactly when each call connects.

The Core Magic: Conference Call Automation

The entire operation revolves around one brilliant insight: Twilio's conference call feature.

Here's how the main function works:

async function main() {
  // First, add yourself to the conference
  const currentCall = await client.calls.create({
    twiml: '<Response><Dial><Conference waitUrl="">collect</Conference></Dial></Response>',
    to: "+39urphonenumber", // Your phone number
    from: phoneN,
  });
  
  // Load all your rented numbers
  const numbers = fs.readFileSync("conference.txt", "utf-8").split("\r\n");
  log(chalk.yellow(`Loaded a total of ${numbers.length} numbers`));
  
  // Launch calls from each number
  let taskNumber = 50;
  for (let i = 0; i < numbers.length; i++) {
    call(numbers[i], taskNumber);
    taskNumber++;
  }
}

The twiml parameter is where the magic happens. It's telling Twilio:

  1. Create a conference room called "collect"
  2. Add anyone who answers to this room
  3. Keep the line open until manually disconnected

The Calling Engine: Persistent and Relentless

Here's the full calling function that makes this unstoppable:

async function call(phoneN, taskN) {
  log(chalk.yellow(`(${phoneN}) [${taskN}] - Starting phone call`));
  
  const currentCall = await client.calls.create({
    twiml: '<Response><Dial><Conference waitUrl="">collectt</Conference></Dial></Response>',
    to: "footlockerphonenumber", // Footlocker's number
    from: phoneN,
  });
  
  const fetchStatus = setInterval(async () => {
    const data = await client.calls(currentCall.sid).fetch();
    
    // Success - you're in the conference
    if (data.status === "in-progress") {
      return log(chalk.green(`(${phoneN}) [${taskN}] - conference started`));
    }
    
    // Call is ringing
    if (data.status === "ringing") {
      return log(chalk.cyan(`(${phoneN}) [${taskN}] - RINGINGGGGGGG`));
    }
    
    // Call ended - restart immediately
    if (data.status === "completed") {
      log(chalk.green(`(${phoneN}) [${taskN}] - Call ended, good job, restarting ;)`));
      clearInterval(fetchStatus);
      return call(phoneN, taskN); // RECURSIVE MAGIC
    }
    
    // Call failed - try again
    if (data.status === "failed" || data.status === "no-answer" || data.status === "busy") {
      log(chalk.red(`(${phoneN}) [${taskN}] - Call failed: ${data.status}, restarting...`));
      clearInterval(fetchStatus);
      return call(phoneN, taskN); // NEVER GIVE UP
    }
    
    // Anti-spam for queued status
    if (data.status === "queued") {
      return;
    }
    
    // Unknown status
    return log(chalk.red(`(${phoneN}) [${taskN}] - Call: ${data.status} waiting...`));
  }, 1000);
}

The Secret Sauce: Status Monitoring

Every second, the script checks each call's status. This real-time monitoring is crucial:

const fetchStatus = setInterval(async () => {
  const data = await client.calls(currentCall.sid).fetch();
  // Status checking logic here
}, 1000); // Check every second

This creates a feedback loop that ensures:

  • Failed calls restart immediately
  • Successful connections are logged
  • Completed calls trigger new attempts
  • No call is ever abandoned

The Numbers File: Your Army of Callers

The script reads phone numbers from a simple text file:

+14155551234
+12125555678
+13105559012
+14085553456
// ... 16 more numbers

Pro tip: Mix area codes. Use some local numbers and some from different cities. It looks more natural than 20 calls from the same area code.

Advanced Tactics: The Voice Game

The code handles the technical side, but the human element matters too:

1. Voice Switching

  • He answers: "Hi, I'd like to reserve the Jordan 4 Black Cats, size 10"
  • Girlfriend takes over: "Hello, can I get a size 7 in the same shoe?"
  • Back to him with slight accent: "Yeah bruv, need a size 11 please"

2. Information Prep Have this ready for each "caller":

  • Different names
  • Different addresses (friends, family, etc.)
  • Payment methods if needed
  • Backstories ("It's my brother's birthday")

3. Conversation Management Since all calls route to one conference, you need to:

  • Mute between different personas
  • Keep track of which "person" is talking
  • Have responses ready for common questions

Error Handling: When Things Go Wrong

The beauty of this system is its resilience. Look at how it handles failures:

if (data.status === "failed" || data.status === "no-answer" || data.status === "busy") {
  log(chalk.red(`(${phoneN}) [${taskN}] - Call failed: ${data.status}, restarting...`));
  clearInterval(fetchStatus);
  return call(phoneN, taskN); // Just try again!
}

No complex retry logic. No exponential backoff. Just pure, relentless persistence.

Failed? Call again. Busy? Call again. No answer? Call again.

It's beautifully simple.

The Exit Strategy

Notice this interesting bit:

if (data.status === "completed") {
  log(chalk.green(`(${phoneN}) [${taskN}] - Call ended, good job, restarting ;)`));
  // call ends if also your main phone ends the call, so we can exit
  process.exit(0);
  clearInterval(fetchStatus);
  return;
}

The commented-out code shows he could either:

  • Exit when done (current setup)
  • Keep calling forever (commented out)

For limited releases, you'd probably want option 2 — keep hammering until you've secured enough pairs.

Optimizations and Variations

Want to take this further? Here are some improvements:

1. Randomized Delays

// Add random delay between calls to seem more human
setTimeout(() => {
  call(numbers[i], taskNumber);
}, Math.random() * 5000); // 0-5 second random delay

2. Call Priority System

// Try local numbers first, then expand
const localNumbers = numbers.filter(n => n.startsWith('+1415'));
const otherNumbers = numbers.filter(n => !n.startsWith('+1415'));

localNumbers.forEach(n => call(n, taskNumber++));
setTimeout(() => {
  otherNumbers.forEach(n => call(n, taskNumber++));
}, 10000); // Add others after 10 seconds

3. Success Tracking

let successfulReservations = 0;
const targetPairs = 5;

// In your success handler:
successfulReservations++;
if (successfulReservations >= targetPairs) {
  log(chalk.green("Target reached! Shutting down..."));
  process.exit(0);
}

4. Store-Specific Configurations

const stores = {
  "broadway": "+14155551234",
  "sunset": "+14155555678",
  "marina": "+14155559012"
};

// Call multiple stores simultaneously
Object.entries(stores).forEach(([location, number]) => {
  log(`Targeting ${location} store...`);
  // Launch calls for each store
});

The Psychology of Automation

What makes this approach so effective isn't just the code — it's the psychological warfare.

Store employees get overwhelmed

  • Their phone rings non-stop
  • Different numbers, different voices
  • The pressure builds

The path of least resistance

  • After 50 calls, they just want it to stop
  • Taking reservations becomes the fastest way to clear the line
  • Your persistence literally forces success

Numbers create legitimacy

  • 20 different phone numbers looks like real demand
  • Multiple voices sound like different customers
  • The store assumes it's genuine interest

Running the Operation

Here's the step-by-step playbook for release day:

1. Night Before

  • Load up conference.txt with your numbers
  • Test with a friend's phone
  • Prep your voice variations
  • Clear your schedule for drop time

2. Drop Day - 5 Minutes Before

node sneaker-bot.js
  • Script starts
  • You're added to the conference
  • All systems ready

3. Drop Time

  • 50 calls blast out simultaneously
  • You wait in the conference
  • First connection appears
  • Start talking

4. Post-Success

  • Note which numbers got through
  • Track successful reservations
  • Plan pickup times
  • Consider sharing success on Twitter (or not)

The Bigger Picture: Why This Matters

This isn't really about gaming Footlocker. It's about recognizing that most "fair" systems aren't fair at all.

The myth of equal access

  • "First come, first served" rewards those with time to waste
  • "Call to reserve" rewards those with fast fingers
  • "Online drops" reward those with the best bots

This developer just leveled the playing field using the same tools available to everyone.

The automation mindset Once you see the world this way, you can't unsee it:

  • DMV appointments booked by hitting refresh
  • Restaurant reservations that open at midnight
  • Any system that wastes human time on mechanical tasks

Each one is an opportunity to build, not suffer.

Code Your Way Out of Stupid Systems

Here's what separates winners from complainers:

Complainers say:

  • "The system is rigged"
  • "It's impossible to get through"
  • "Rich kids with bots ruin everything"

Builders say:

  • "How does this system work?"
  • "What are its weak points?"
  • "How can I automate this?"

One mindset leaves you empty-handed and bitter. The other gets you every pair you want.

Your Next Steps

1. Identify your "Footlocker" What system is wasting your time? What process makes you want to throw your phone?

2. Break it down What's the core action? Calling? Clicking? Refreshing? There's always a simple pattern.

3. Find the right tool

  • Twilio for phones
  • Puppeteer for browsers
  • APIs for everything else

4. Start simple Don't build for 50 numbers on day one. Make it work with 2, then scale.

5. Share the knowledge This developer open-sourced his code. When you build something cool, consider doing the same.

The Uncomfortable Truth Nobody Wants to Admit

Every "fair" system has already been automated by someone smarter than the system's designers.

Concert tickets? Bots buy them in milliseconds. Supreme drops? Automated checkouts. Restaurant reservations? Scripts book them instantly.

You can either pretend this isn't happening, or you can join the arms race.

Because here's the thing: Footlocker probably knew this was happening. They just didn't care enough to fix it. A broken system that moves inventory is still a system that moves inventory.

Stop Playing by Rules That Don't Exist

The sneaker game rewards those who refuse to play by imaginary rules.

There's no honor in manually calling 100 times. There's no prize for wasting your Saturday morning. There's no medal for "doing it the right way."

There's only one question: Did you get the shoes?

This developer did. Every single time.

And now, with his code in your hands, so can you.

The only question left is: What will you automate next?

This story is based on a X post, you can find here.

Marius Bernard

Marius Bernard

Marius Bernard is a Product Advisor, Technical SEO, & Brand Ambassador at Roundproxies. He was the lead author for the SEO chapter of the 2024 Web and a reviewer for the 2023 SEO chapter.