I spent $20 on Aliexpress and got three unreliable 8GB SD cards
Quite a lot of Japanese people are probably shopping on Aliexpress and Taobao by now. Most of them have probably ended up with cheap junk at some point, seething or stomping their feet, thinking “never again,” or “how is this even legal,” or “how does this even work as a business.” This time I decided to do it “for fun.”
That is:
Buy an insanely cheap SD card on Aliexpress and see what happens.
That’s the premise.
With Claude Code helping me out, I checked things like “what’s the real capacity?” and “what’s the actual transfer speed?” and in the end repartitioned the ones that behaved reasonably well to match their actual capacity and got them into a usable state.
The final result was as stated in the title (whether it was worth it comes out slightly on the losing side, lol), and I had Claude Code write up the record of that battle, so anyone interested should give it a read.
I bought 6 SD cards separately from multiple “sketchy stores” and checked their capacity by writing to offsets on the raw device. All 6 cards turned out to be capacity-faked. But the way they lied wasn’t uniform — they split into several distinct implementation-level families.
0.46% Against a combined claimed capacity of 5,028.5 GiB across the 6 cards, the actual data that could be held was 23.4 GiB.
Advertised capacity vs. actual capacity
The bar in each row is drawn to actual scale, with the advertised capacity as the full width. The bottom two are narrower than one pixel, so they’re shown at the minimum width.
#1 32GB 122.83 MiB 0.410%
#2 2TB 7.136 GiB 0.357%
#3 1TB 108.28 MiB 0.011%
#4 1TB 108.28 MiB 0.011%
#5 512GB 7.953 GiB 1.591%
#6 512GB 7.937 GiB 1.588%
The usable-capacity ratio spans two orders of magnitude, from 0.011% to 1.59%. There’s no common design value like “load a fixed fraction of the advertised capacity.”
The actual capacities split into two clusters
Plotting actual capacity on a log axis, the 6 cards split cleanly into two groups — a 128MB class and an 8GB class — with nothing in between. This has nothing to do with the label capacity: the two cards claiming 1TB were the smallest.
128MB class 8GB class
100 MiB 512 MiB 1 GiB 2 GiB 4 GiB 8 GiB
#1 · 32GB 122.83 MiB #2 · 2TB 7.14 GiB #3 · 1TB 108.28 MiB #4 · 1TB 108.28 MiB #5 · 512GB 7.95 GiB #6 · 512GB 7.94 GiB
The horizontal axis is logarithmic. #3 and #4 overlap at the same point.
Full record of all units
| # | Label | Reported bytes | Actual capacity | Usable ratio | Fake type | Shipped FS |
|---|---|---|---|---|---|---|
| 1 | 32GB | 31,458,328,576 | 122.83 MiB | 0.4095% | DISCARD | FAT32 |
| 2 | 2TB | 2,147,483,648,000 | 7.136 GiB | 0.3568% | ECHO | FAT32 |
| 3 | 1TB | 1,073,741,824,000 | 108.28 MiB | 0.0106% | DISCARD | NTFS |
| 4 | 1TB | 1,072,902,963,200 | 108.28 MiB | 0.0106% | DISCARD | NTFS |
| 5 | 512GB | 536,870,912,000 | 7.953 GiB | 1.5907% | DISCARD | FAT32 |
| 6 | 512GB | 536,870,912,000 | 7.937 GiB | 1.5876% | DISCARD | FAT32 |
None of the 6 cards showed a “tail window” — the trick of allocating real flash only at the end of the device to pass naive checks.
There were two ways of lying
They can be classified by how the controller responds to writes beyond actual capacity. In both types, dd returns success on the write. A genuinely failed flash chip would return an I/O error, so this “normal response” itself is evidence of the fake.
5 / 6 cards
DISCARD — silently drops the data
The device accepts the write beyond actual capacity, reports success, and simply discards it. Reading it back returns zeros.
The data doesn’t exist from the moment it’s written, and no error is raised. This is the kind of failure where you keep shooting photos and end up with a pile of files that later won’t open.
1 / 6 cards · #2
ECHO — returns the last write
Reading an unimplemented address returns whatever block was written most recently. All 31 probes returned the identical stamp.
Since this isn’t address wraparound, you can’t back-calculate from the remainder. And it reliably passes the “read back what you just wrote” check.
The same hardware, different lies
There were two pairs sharing the same label, and in both pairs, only one of the two matching attributes lined up.
#3 and #4 — identical hardware, different descriptors
Independent binary searches converged on the same boundary block. DISCARD type, no tail window, shipped as NTFS — all identical. But the fake-capacity descriptor differs.
#3 1,073,741,824,000 bytes = exactly 1000 GiB #4 1,072,902,963,200 bytes = exactly 1,023,200 MiB
One is set in GiB units, the other in MiB units. This suggests that after a common base component was distributed, the capacity was rewritten separately per lot or per vendor.
#5 and #6 — identical descriptor, different hardware
The reported byte counts match exactly, yet the actual capacity differs by exactly 16.00 MiB. Same base component, but the amount judged to be good flash differs slightly. This is the mirror image of #3/#4.
#5 8,144.50 MiB #6 8,128.50 MiB difference 16.00 MiB
Spotting it before you even test
The most effective fingerprint can be confirmed without writing anything at all.
Fakes report “more” capacity than the label
#2, #3, #5, and #6 all had the label’s number set directly as GiB. A genuine product would set the same number as GB. Whoever wrote the fake capacity confused GB and GiB, so the reported bytes come out roughly 7.4% higher than a genuine product would show.
Genuine 1TB → roughly 931 GiB / roughly 1000 GB Fake 1TB → exactly 1000 GiB / 1073.7 GB
If the reported byte count is a clean multiple of 2^30, suspect a fake right away. A genuine product’s capacity comes out as an odd number. #1 was the only one of the 6 without this trait — its reported value of 30,001 MiB was a number consistent with a genuine product.
- Shipped formatted as NTFS or FAT32. A legitimate manufacturer would never ship an SD card as NTFS. exFAT is the standard for high-capacity cards. NTFS is the trace left by whoever wrote the fake capacity, formatting it on a Windows machine.
- The combination of 2.1TB, FAT32, and MBR. Both FAT32’s volume limit and MBR’s limit are 2TiB. A capacity that sits exactly at the spec ceiling is unnatural.
- Abnormally slow writes. #1 only managed 1.3 MB/s. A genuine Class 10 card should hit at least 10 MB/s, with 20–90 MB/s in practice.
The “write then immediately read back” check doesn’t work
Full verification by writing across the entire capacity is reliable, but at a combined 5TB it would take anywhere from tens of hours to tens of days. So instead, at each chosen offset on the raw device, I wrote a 4KiB block stamped with that offset itself, then read it back to check consistency. This takes about a minute per card.
But this method has a pitfall. Since ECHO-type cards return the last write for unimplemented addresses, reading back offset X right after writing X will always match. This check ends up reporting the entire faked-capacity range as “normal.”
In fact, the boundary-detection script I wrote first had exactly this flaw: it reported #2 — whose actual capacity is 7.1 GiB — as “the full 2TB is genuine.” I caught this through a regression test against an emulated fake device.
The fix is to insert a decoy write to a different address between the write and the read. If the device is an echo type, the decoy’s contents get returned instead, exposing it. Decoys need to be placed at both low and high addresses. In implementations that route only writes to unimplemented addresses through a buffer, a low-address decoy that lands in real storage never touches that buffer.
There was another source of false positives: the card’s volatile cache. #1 initially seemed to read back correctly only at its final block, leading me to conclude it “has a tail window” — but this was wrong. That block simply happened to be the last one written, and the read was served from cache. Determining whether a device has a tail window is sensitive to write order.
The 3 cards in the 8GB class could be salvaged
Since the fake capacity is written into the controller itself, the capacity value can’t be fixed. What can be done is to confine the filesystem to just the range where flash actually exists. Here, all 6 cards’ binary searches converged monotonically, confirming that the real storage is contiguous starting from offset 0. For cards where this assumption breaks down (real storage scattered non-contiguously), this technique wouldn’t work.
I repartitioned the 3 cards in the 8GB class to their actual capacity. Since flash erase blocks are far larger than the 4KiB resolution of the boundary search, I kept roughly 10% as a safety margin. #5 and #6 were set to 7200M, and #2, with its smaller actual capacity, to 6500M.
diskutil partitionDisk /dev/disk4 MBRFormat ExFAT SDCARD 7200M “Free Space” %noformat% R
sudo wasn’t required. I ran a full verification on all 3 cards in this state.
Data OK LOST write read #5 6.69 GB 0.00 B 17.63 MB/s (6 min 29 sec) 23.26 MB/s #6 6.69 GB 0.00 B 14.51 MB/s (7 min 56 sec) 22.94 MB/s #2 6.04 GB 0.00 B 8.74–10.23 MB/s 22.63 MB/s
All 3 cards showed zero corruption, alteration, or overwrite. Within their actual capacity, this flash is sound. Speeds were reasonable for cheap cards too, with nothing as abnormal as #1’s 1.3 MB/s.
That said, being salvageable doesn’t mean they should be trusted. Since these are fakes, they’re highly likely to be using flash that failed quality selection, and their durability and data-retention period are unknown. A genuine 8GB card from a decent manufacturer can be bought for a few dollars, so there’s no economic reason to bother using these. Don’t trust them with anything important.
#2, however, needs to be treated as a special case. The controller crashed partway through the exFAT format. The partition and filesystem had been written correctly, but the subsequent mount failed, and the entire block device dropped off the bus. It came back after unplugging and replugging, the filesystem was intact, and the full verification afterward passed. It also had the slowest write speed of the 3 cards, and — uniquely — it slowed down over the course of the test, from 10.23 MB/s on the first GB to 8.74 MB/s at the end. The other two stayed constant throughout.
Beyond that, after verification, diskutil verifyVolume detected corruption in the exFAT allocation bitmap. Even after deleting files, 905 MiB remained marked as in use, and unmounting and remounting didn’t resolve it. diskutil repairVolume repaired it. But since f3read had passed verification of every sector, the data blocks themselves had been written correctly, and the corruption was confined to filesystem metadata. It seems natural to attribute this to the crash during formatting.
#2 is also the only ECHO-type card among the 6, but whether that’s related to its instability can’t be determined from this testing.
The 3 cards whose actual capacity was 108–123 MiB aren’t usable at any practical capacity even with the same procedure.
Limits of this record
Boundary detection relies on a binary search that assumes real storage is contiguous. Since all 6 cards’ searches converged monotonically, the values can be trusted, but this assumption breaks down for irregular cards where real storage is scattered non-contiguously. In that case you’d need to examine the raw list of all probes.
Also, a “pass” on this check only guarantees that the capacity is genuine — flash health is a separate matter. Cards that pass still need a separate full verification. Since all 6 cards here failed, once the capacity fraud was confirmed I didn’t proceed to that stage (I only ran full verification on #6 after salvage).
Test date: 2026-09-09 / macOS 15.6 (Darwin 24.6.0) / via USB card reader Genesys Logic 05e3:0764 Probe block: 4096 bytes · offsets at powers of 2, 1.5x points, and 16 evenly spaced points across the full range · boundary detection: binary search at 4KiB resolution · full verification: f3 10.0
Originally published in Japanese at https://clazytech.com/2026/09/1805/. Translated with LLM assistance and reviewed before publication.