Turn Kindle Paperwhite e-reader into a development and production tool.
- Copy
javascript.html
to your Kindle (not in subfolder for starters) - Open Experimental Browser (Three-vertical-dots menu > Experimental Browser).
- In the address bar, type
file:///mnt/us/javascript.html?alert('Hi\x20there!')
(if you switch the Kindle off before closing the message, it will stay on screen! You can use it to leave messages.)
- or type
file:///mnt/us/javascript.html?25*4+1
for a calculator - or type
file:///mnt/us/javascript.html?Date()
for a clock - or type the content of dev.txt for an IDE with its own code being open in the text editing window
- bookmark it, type code, get a blank screen (that is proabbly a parse error), get frustrated, find solutions, enjoy, share
Amazon Kindle Paperwhite is a standalone portable computer that provides:
- a great B/W touchscreen,
- low computation power,
- limited access to the internal memory.
And also, it is primarily an e-reader. This project's target device is Kindle Paperwhite 3, (i. e. 7th Generation, year 2015) running the firmware version Kindle 5.12.3 (the most recent in 2020). How to know which Kindle you have?
This project contains resources and examples that I found useful to get the maximum of this device. The features generally rely on the "Experimental Web Browser". No jailbreak, no root access nor any other modification that would breach any conditions of use or warranty is required.
Kindle incorporates a Web Browser that is not documented and not many resources about it were available in 2020. It is not a "modern" web-browser but has HTML5 capabilities and supports JavaScript (limited ES5), and it interprets XSLT using libxslt v1.0.
- When accessing a unsuported URL, an error message claims that
only HTTP and HTTPS protocols are supported. - In reality, the main storage user storage space is available via URL file:///mnt/us
- It gives you a browsable directory listing (including hidden files starting with a
.
)- Its webpage title is "OMG!" which is about what goes through your mind when you discover that you actually can view the content of your device.
- It gives you a browsable directory listing (including hidden files starting with a
- DataURI (
data:
) works only if generated by a link, not if entered in the address bar, not if loaded from bookmark. - Address bar JS
javascript:
does not work. - So far only files with following extensions are rendered: TXT, HTML, HTM, JPG, JPEG, PNG, XML. In any upper/lower-case combination. The list might be incomplete. Otherwise, you get an error message claiming that
Only files with extension .AZW, .PRC, .MOBI or .TXT can be downloaded to your Kindle.- Sidenote: when you load or generate a TXT file, I could not find a way how to download it. It always shows in the Browser and there is no "save as" or "download" option anywhere. So far, only working method to make dowload is to serve it with a header of
Content-Type
application/octet-stream
, for example
- Sidenote: when you load or generate a TXT file, I could not find a way how to download it. It always shows in the Browser and there is no "save as" or "download" option anywhere. So far, only working method to make dowload is to serve it with a header of
node -e "express=require('express');app=express();app.get('/', (req,res)=>{res.set('Content-Type', 'application/octet-stream');res.download('test.txt')});app.listen(3000)"
- The Experimental Web Browser does not have any access to the storage space
- Cookies for file:/// protocol are stored only for the current session
- LocalStorage stored only for the current session
- Current session ends when "home" button is pressed (or back button leads you to the welcome screen)
- Some constructors are missing (e.g.
new Blob()
would throw a rather absurd-sounding exception'[object BlobConstructor]' is not a constructor
)- It includes all
Event
constructors, which means that event dispatching is an open issue (e.g. if we want to focus a text field)
- It includes all
- Touch or mouse down/up events are not triggered
- The constructor
new WebSocket
doesn't show any error; the newly created websocket immediately dies - callingonclose()
without any return code nor reason norwasClean
flag.
- Script's tag
src
attribute generated bydocument.write
gets replaced byabout:blank
<script src="https://raw.githubusercontent.com/eligrey/Blob.js/master/Blob.js"></script>
becomes
<script src="about:blank"></script>
- hyperlinks are always underlined because the browser injects following
<style>
element:
<style type="text/css">a:-webkit-any-link{text-decoration: underline !important;}</style>
prompt()
dialog gets confirmed when space character is inserted (i.e. with on-screen keyboard), it supports text selection with press-and-drag- Address bar interactions with text selection and navigation:
- press and drag works but need to stay in line!
- touching upper border of the addressbar during selection makes selection till the begining of the URL
- touching lower border takes you to the end of the URL
- press and drag works but need to stay in line!
<textarea>
in a HTML form does not support gestures for selecting text (although it is possible programatically)- Visual feedback on pressing a button: happens only once (second time, there is no change of appearance and Kindle doesn't redraw)
- Screenshot: press top-left and bottom-right corner at the same time. The screen flickers and stores the picture in the root directory as
screenshot_2020_09_16T22_02_03+0800.png
with the structurescreenshot_yyyy_mm_ddTHH_MM_SS+ZZZZ.png
year, month, day, hour, minute, second, timeZone. - A URL can be at least 2 million characters long (reached with an incremental JS approach but the device get slow)
- Unfortunately it cannot be bookmarked. There seems to be a hard limit of overall size of the bookmarks higher than 33,000 characters.
~ds
Screen always on (will drain the battery!).- Into search bar of main screen or address bar of the web browser type:
~ds
it stands for "disable screensaver' - Useful when using as a message board, wall clock and continuously powered
- Switch screen off once (long-press the bottom button > Screen Off) -- blank, no Kindle image
- Re-enable screensaver by rebooting the device (Settings > Device Options > Restart)
- Into search bar of main screen or address bar of the web browser type:
;411
Screen temperature (and other info, firmware, time offset, ...);711
List wifi networks MAC, channel, AP MAC, available networks with encryptions, current IP, DNS- external link to more search bar codes
- My screenshots were timestamped with
+0759
timezone (and I kept wondering why the clock on my Kindle is always a minute behind) until I fixed it by setting the time manually again. For JavaScript, the Kindle's timezone is almost always UTC. It means that inside JS, you can never deduce in which timezone you are! The offset is determined when the user sets the time and it seems only a hidden setting. (It would be possible to get the offset from screenshots though - as we can work with iframes, load a content of file:///mnt/us and parse it, find filenames matching the screenshot pattern and voilà.) Date()
shows the correct date with the right timezone offset however, usingnew Date()
ruins it. To reset, Home button and starting Web browser does the trick andDate()
works again. WEIRD- I found no way to turn the backlight completely off.
- Kindle does not provide Copy and Paste functionalities (an implementation is possible through
localstorage
)
root directory: the place that shows up on your regular compuer when you plug your Kindle in.
If you don't want to use Tesseract on your screenshots to get your source code in a pull request, here is another way:
-
Find out IP address of the computer where you want to get the code to:
ifconfig | grep "inet "
on Unix-like systems oripconfig
in Windows which is usually of the form192.168.xx.xx
or10.xx.xx.xx
. In my example, it shows192.168.1.100
-
Install Node.js and run the following command line (on MacOS Terminal.app, on Windows PowerShell, Command Prompt (
cmd
), or Cygwin, on Linux any console/terminal)
node -e "require('http').createServer((req, res) => {console.log(req.url.substr(1));res.statusCode=200;res.end()}).listen(3000)"
- It runs a server on your machine that listens on port 3000 for incomming connections and writes the URL they were requesting in the standard output.
- Connect your Kindle on your Wi-Fi (same as your computer)
- Navigate to your excellent script file://mnt/us/javascript.html?try{this-is-a-very-long-code-that-would-take-ages-to-transcribe}catch(e){alert(e)}
- In the beginning of the URL, type
http://192.168.1.100:3000/
(where you replace by your actual IP address) - Confirm and now it appears on your computer, magic!