Skip to content

Instantly share code, notes, and snippets.

@jevakallio
Last active April 8, 2025 09:33
Show Gist options
  • Save jevakallio/452c54ef613792f25e45663ab2db117b to your computer and use it in GitHub Desktop.
Save jevakallio/452c54ef613792f25e45663ab2db117b to your computer and use it in GitHub Desktop.
`adb pull` from app data directory without root access

TL;DR;

com.package.name is your app identifier, and the file path is relative to the app user's home directory, e.g. '/data/user/0/com.package.name.

adb shell run-as com.package.name cp relative/path/file.ext /sdcard
adb pull /sdcard/file.ext

See long explanation below.

Problem

Trying to adb pull files from our app's directory fails with Permission denied, because the adb user doesn't have access to the home directory.

adb pull /data/user/0/com.package.name/file.ext

Error:

adb: error: failed to stat remote object '/data/user/0/com.package.name/file.ext': Permission denied

You can try to run adb as root first:

adb root

But on a non-rooted device, this fails with:

adbd cannot run as root in production builds`

Here's a workaround on how to download a file from the app data directory using run-as.

Long version

This explains the solution step by step.

Start a shell session on the device. All following commands will be executed in the shell session on your device.

adb shell

Assuming our app identifier is com.package.name, the app data directory is at /data/user/0/com.package.name.

You can try to list files in that directory:

ls /data/user/0/com.package.name

This should result in error:

ls: /data/user/0/com.package.name/: Permission denied

However, you can run a command using the com.package.name application identity with the run-as command

run-as com.package.name ls /data/user/0/com.package.name/

You should now see a directory listing, and you can find the file you want, and copy it to a directory on your device that doesn't require root access, e.g. /sdcard:

run-as com.package.name cp /data/user/0/com.package.name/file.ext /sdcard

We can then exit the adb shell:

exit

Back at our own computer, we can adb pull the file:

adb pull /sdcard/file.ext
@briandyy
Copy link

briandyy commented Nov 1, 2024

this will remove the file data before backed up

@sbpetrack
Copy link

The following is the basis of a solution that does not require making an apk debuggable, nor copying any file within the phone, nor any chmod command. MUCH more significantly (I think?), it overcomes a problem that hasn't yet been mentioned here, which is the fact that adb pull doesn't work with wildcards or globbing -- the examples above push or pull a single file (except perhaps for the solutions that use adb backup, and 1. adb backup is deprecated; and 2. i'm not sure, but i think with adb backup you can only back up an individual file or everything. In any case, I hope some might find the following useful.

Preface: I ran adb root before any of this. On my Magisk-rooted phone (OnePlus 10 Pro 5G running Oxygen/Android 15), I can run adb root via the following three commands. (The first can be entered into an adb shell, but the last can only be entered into a root shell on the phone. I just type them all into a rooted termux shell):

#resetprop   ro.debuggable 1  
#adbd stop
#adbd start

Then I can successfully run adb root on my laptop. After that, here is a transcript of part of an xterm session from my laptop (running bash on arch linux; adapt as you see fit). The commands at the beginning are there just to make clear that even after adb root, there are things you can't do without some extra nonsense:

[scott@scott-xps9500 account1]$  adb shell  ls -l /data/data/org.telegram.messenger/files/account1/* 
ls: /data/data/org.telegram.messenger/files/account1/*: Permission denied

[scott@scott-xps9500 account1]$  adb shell su -c  ls -l /data/data/org.telegram.messenger/files/account1/* 
-rw------- 1 u0_a325 u0_a325    4096 2025-03-18 08:43 /data/data/org.telegram.messenger/files/account1/cache4.db
-rw------- 1 u0_a325 u0_a325   32768 2025-03-29 10:35 /data/data/org.telegram.messenger/files/account1/cache4.db-shm
-rw------- 1 u0_a325 u0_a325 2220712 2025-03-18 08:43 /data/data/org.telegram.messenger/files/account1/cache4.db-wal
-rw-rw---- 1 u0_a325 u0_a325      40 2025-03-29 10:35 /data/data/org.telegram.messenger/files/account1/dc2conf.dat
-rw------- 1 u0_a325 u0_a325     612 2025-03-29 10:35 /data/data/org.telegram.messenger/files/account1/stats2.dat
-rw-rw---- 1 u0_a325 u0_a325    1580 2025-03-29 10:35 /data/data/org.telegram.messenger/files/account1/tgnet.dat

[scott@scott-xps9500 account1]$  adb shell su -c  ls  /data/data/org.telegram.messenger/files/account1/* 
/data/data/org.telegram.messenger/files/account1/cache4.db
/data/data/org.telegram.messenger/files/account1/cache4.db-shm
/data/data/org.telegram.messenger/files/account1/cache4.db-wal
/data/data/org.telegram.messenger/files/account1/dc2conf.dat
/data/data/org.telegram.messenger/files/account1/stats2.dat
/data/data/org.telegram.messenger/files/account1/tgnet.dat

[scott@scott-xps9500 account1]$  for file in `adb shell su -c ls /data/user/0/org.telegram.messenger/files/account1/* ` 
> do
> adb shell su -c dd if=$file > `basename $file`
> done
8+0 records in
8+0 records out
4096 bytes (4.0 K) copied, 0.001 s, 3.9 M/s
64+0 records in
64+0 records out
32768 bytes (32 K) copied, 0.002 s, 16 M/s
4337+1 records in
4337+1 records out
2220712 bytes (2.1 M) copied, 0.050 s, 42 M/s
0+1 records in
0+1 records out
40 bytes (40 B) copied, 0.001 s, 39 K/s
1+1 records in
1+1 records out
612 bytes (612 B) copied, 0.001 s, 598 K/s
3+1 records in
3+1 records out
1580 bytes (1.5 K) copied, 0.001 s, 1.5 M/s

[scott@scott-xps9500 account1]$ ls -l
total 2220
-rw-r--r-- 1 scott scott    4096 Mar 29 12:57 cache4.db
-rw-r--r-- 1 scott scott   32768 Mar 29 12:57 cache4.db-shm
-rw-r--r-- 1 scott scott 2220712 Mar 29 12:57 cache4.db-wal
-rw-r--r-- 1 scott scott      40 Mar 29 12:57 dc2conf.dat
-rw-r--r-- 1 scott scott     612 Mar 29 12:57 stats2.dat
-rw-r--r-- 1 scott scott    1580 Mar 29 12:57 tgnet.dat

Note 1: (if you care) that both permissions and ownership of the copied files do not match the originals. (The change in ownership is hardly surprising, as there is no user u0_325 on my laptop. I'll leave as another "exercise for the reader" to add to the bash "for" loop the commands that read the file permissions from the phone and write them on the laptop).

Note 2: I have forever use a command like

adb pull  `adb shell ls path/with/wildcards/*.whatever `      target-dir/

to pull multiple files or directories (recursively or not) with adb pull. I found this page when confronted with the permissions problems as well. So thank you to @tuanchauict and @listvin for mentioning dd! Let us hope that android file security remains as arbitrary and inconsistent as it is today, so that we can get our work done. BTW, on that subject:

Note 3: For many of you, you don't need to do ANY of this: the next time you are having trouble to pull or push a file over adb, try each of the following ways to refer to the directory on the phone you are trying to access: /data/media/0/ or /sdcard/ or /storage/emulated/0 . On my phone, for example, when not using root privileges, I usually can only see files under /sdcard/ (I get "permission denied" for the other two names for the same directory); but when referring to the same directory via adb push or adb pull on my laptop, i can only see/access files under /data/media/0 (the other choices get me "permission denied" ). C'est logique!!

@cleoold
Copy link

cleoold commented Apr 8, 2025

The following is the basis of a solution that does not require making an apk debuggable, nor copying any file within the phone, nor any chmod command. MUCH more significantly (I think?), it overcomes a problem that hasn't yet been mentioned here, which is the fact that adb pull doesn't work with wildcards or globbing -- the examples above push or pull a single file (except perhaps for the solutions that use adb backup, and 1. adb backup is deprecated; and 2. i'm not sure, but i think with adb backup you can only back up an individual file or everything. In any case, I hope some might find the following useful.

Preface: I ran adb root before any of this. On my Magisk-rooted phone (OnePlus 10 Pro 5G running Oxygen/Android 15), I can run adb root via the following three commands. (The first can be entered into an adb shell, but the last can only be entered into a root shell on the phone. I just type them all into a rooted termux shell):

#resetprop   ro.debuggable 1  
#adbd stop
#adbd start

Then I can successfully run adb root on my laptop. After that, here is a transcript of part of an xterm session from my laptop (running bash on arch linux; adapt as you see fit). The commands at the beginning are there just to make clear that even after adb root, there are things you can't do without some extra nonsense:

[scott@scott-xps9500 account1]$  adb shell  ls -l /data/data/org.telegram.messenger/files/account1/* 
ls: /data/data/org.telegram.messenger/files/account1/*: Permission denied

[scott@scott-xps9500 account1]$  adb shell su -c  ls -l /data/data/org.telegram.messenger/files/account1/* 
-rw------- 1 u0_a325 u0_a325    4096 2025-03-18 08:43 /data/data/org.telegram.messenger/files/account1/cache4.db
-rw------- 1 u0_a325 u0_a325   32768 2025-03-29 10:35 /data/data/org.telegram.messenger/files/account1/cache4.db-shm
-rw------- 1 u0_a325 u0_a325 2220712 2025-03-18 08:43 /data/data/org.telegram.messenger/files/account1/cache4.db-wal
-rw-rw---- 1 u0_a325 u0_a325      40 2025-03-29 10:35 /data/data/org.telegram.messenger/files/account1/dc2conf.dat
-rw------- 1 u0_a325 u0_a325     612 2025-03-29 10:35 /data/data/org.telegram.messenger/files/account1/stats2.dat
-rw-rw---- 1 u0_a325 u0_a325    1580 2025-03-29 10:35 /data/data/org.telegram.messenger/files/account1/tgnet.dat

[scott@scott-xps9500 account1]$  adb shell su -c  ls  /data/data/org.telegram.messenger/files/account1/* 
/data/data/org.telegram.messenger/files/account1/cache4.db
/data/data/org.telegram.messenger/files/account1/cache4.db-shm
/data/data/org.telegram.messenger/files/account1/cache4.db-wal
/data/data/org.telegram.messenger/files/account1/dc2conf.dat
/data/data/org.telegram.messenger/files/account1/stats2.dat
/data/data/org.telegram.messenger/files/account1/tgnet.dat

[scott@scott-xps9500 account1]$  for file in `adb shell su -c ls /data/user/0/org.telegram.messenger/files/account1/* ` 
> do
> adb shell su -c dd if=$file > `basename $file`
> done
8+0 records in
8+0 records out
4096 bytes (4.0 K) copied, 0.001 s, 3.9 M/s
64+0 records in
64+0 records out
32768 bytes (32 K) copied, 0.002 s, 16 M/s
4337+1 records in
4337+1 records out
2220712 bytes (2.1 M) copied, 0.050 s, 42 M/s
0+1 records in
0+1 records out
40 bytes (40 B) copied, 0.001 s, 39 K/s
1+1 records in
1+1 records out
612 bytes (612 B) copied, 0.001 s, 598 K/s
3+1 records in
3+1 records out
1580 bytes (1.5 K) copied, 0.001 s, 1.5 M/s

[scott@scott-xps9500 account1]$ ls -l
total 2220
-rw-r--r-- 1 scott scott    4096 Mar 29 12:57 cache4.db
-rw-r--r-- 1 scott scott   32768 Mar 29 12:57 cache4.db-shm
-rw-r--r-- 1 scott scott 2220712 Mar 29 12:57 cache4.db-wal
-rw-r--r-- 1 scott scott      40 Mar 29 12:57 dc2conf.dat
-rw-r--r-- 1 scott scott     612 Mar 29 12:57 stats2.dat
-rw-r--r-- 1 scott scott    1580 Mar 29 12:57 tgnet.dat

Note 1: (if you care) that both permissions and ownership of the copied files do not match the originals. (The change in ownership is hardly surprising, as there is no user u0_325 on my laptop. I'll leave as another "exercise for the reader" to add to the bash "for" loop the commands that read the file permissions from the phone and write them on the laptop).

Note 2: I have forever use a command like

adb pull  `adb shell ls path/with/wildcards/*.whatever `      target-dir/

to pull multiple files or directories (recursively or not) with adb pull. I found this page when confronted with the permissions problems as well. So thank you to @tuanchauict and @listvin for mentioning dd! Let us hope that android file security remains as arbitrary and inconsistent as it is today, so that we can get our work done. BTW, on that subject:

Note 3: For many of you, you don't need to do ANY of this: the next time you are having trouble to pull or push a file over adb, try each of the following ways to refer to the directory on the phone you are trying to access: /data/media/0/ or /sdcard/ or /storage/emulated/0 . On my phone, for example, when not using root privileges, I usually can only see files under /sdcard/ (I get "permission denied" for the other two names for the same directory); but when referring to the same directory via adb push or adb pull on my laptop, i can only see/access files under /data/media/0 (the other choices get me "permission denied" ). C'est logique!!

Did you see the description of the gist, ... without root access?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment