Skip to content

Instantly share code, notes, and snippets.

@mvance

mvance/README.md Secret

Last active January 27, 2026 18:57
Show Gist options
  • Select an option

  • Save mvance/1a971f735db0c93bbe9914d26f9e9308 to your computer and use it in GitHub Desktop.

Select an option

Save mvance/1a971f735db0c93bbe9914d26f9e9308 to your computer and use it in GitHub Desktop.
Libby Audiobook Downloader Bookmarklets

Libby Audiobook Downloader Bookmarklets

This repository contains two bookmarklets that help you download MP3 files from Libby audiobooks. These tools allow you to:

  1. Extract MP3 file URLs from a Libby audiobook
  2. Process cURL commands to generate download scripts

Note: These bookmarklets were generated using AI code generation.

Installation

To install these bookmarklets:

  1. Create two new bookmarks in your browser
  2. Name them something recognizable like "Libby Extract URLs" and "cURL Processor"
  3. For each bookmark, paste the corresponding JavaScript code below into the URL/location field

Bookmarklet 1: Extract MP3 URLs

javascript:(function(){  try {    const playButton = document.querySelector('button[aria-label="Play audiobook"].mini-player-playback-toggle');        if (playButton) {      playButton.click();    }        function triggerAdvance() {      try {        const jumpBtn = document.querySelector('button[aria-label="Advance 15 seconds"].mini-player-jump-ahead');        if (jumpBtn) {          jumpBtn.click();          jumpBtn.dispatchEvent(new MouseEvent('mousedown', {bubbles: true}));          jumpBtn.dispatchEvent(new MouseEvent('mouseup', {bubbles: true}));          jumpBtn.dispatchEvent(new MouseEvent('click', {bubbles: true}));        }      } catch(e) {        console.error(e);      }    }        const advanceInterval = setInterval(triggerAdvance, 100);        document.addEventListener('keydown', function escapeHandler(e) {      if (e.key === 'Escape') {        clearInterval(advanceInterval);        document.removeEventListener('keydown', escapeHandler);      }    });  } catch(e) {    console.error(e);  }})();

Bookmarklet 2: cURL Command Processor

This bookmarklet helps process multiple cURL commands copied from Chrome's "Copy as cURL" feature. It performs the following operations:

  1. Extracts book title from the page title (from "Libby - Open: [Book Title]")
  2. Creates a directory based on the book title (with proper sanitization to lowercase with underscores)
  3. Removes duplicate URLs (keeping only the first instance of each unique URL)
  4. Removes all -H 'range: bytes=*-' \ lines
  5. Adds sequential output filenames (-o file-01.mp3, -o file-02.mp3, etc.)
  6. Adds the --location argument to each curl invocation to follow redirects
  7. Adds an mp3wrap command at the end to concatenate all downloaded files
  8. Adds a command to open the concatenated file in QuickTime Player
  9. Returns the processed commands in a text box for easy copying
javascript:(function(){const e=document.createElement("div");e.style.cssText="position: fixed;top: 0;left: 0;width: 100%;height: 100%;background-color: rgba(0, 0, 0, 0.7);display: flex;justify-content: center;align-items: center;z-index: 10000;font-family: Arial, sans-serif;";const t=document.createElement("div");t.style.cssText="background-color: white;padding: 20px;border-radius: 5px;width: 80%;max-width: 800px;max-height: 90%;display: flex;flex-direction: column;overflow: hidden;";const n=document.createElement("h2");n.textContent="cURL Command Processor",n.style.cssText="margin-top: 0;color: #333;";const o=document.createElement("p");o.textContent='Paste cURL commands below and click "Process"',o.style.cssText="margin-bottom: 15px;color: #555;";const r=document.createElement("textarea");r.style.cssText="width: 100%;height: 200px;margin-bottom: 15px;padding: 10px;border: 1px solid #ccc;border-radius: 4px;resize: vertical;font-family: monospace;font-size: 14px;",r.placeholder="Paste cURL commands here...";const a=document.createElement("button");a.textContent="Process",a.style.cssText="background-color: #4CAF50;color: white;padding: 10px 15px;border: none;border-radius: 4px;cursor: pointer;font-size: 16px;align-self: center;margin-bottom: 15px;";const l=document.createElement("textarea");l.style.cssText="width: 100%;height: 200px;margin-bottom: 15px;padding: 10px;border: 1px solid #ccc;border-radius: 4px;resize: vertical;font-family: monospace;font-size: 14px;",l.placeholder="Processed commands will appear here...",l.readOnly=!0;const c=document.createElement("button");function i(){const e=r.value;if(!e.trim())return void(l.value="No input provided.");try{let t="";const n=document.querySelector("title");if(n){const e=n.textContent;if(console.log("Page title:",e),e.includes("Libby - Open:")){t=e.split("Libby - Open:")[1].trim(),console.log("Extracted book title:",t)}}let o="";t?(o=t.replace(/[^a-zA-Z0-9]/g,"_").toLowerCase(),o=o.replace(/_+/g,"_"),o=o.replace(/^_|_$/g,""),console.log("Directory name:",o)):o="audiobook_download";const a=e.match(/curl\s+'[^']+'/g)||[],c=new Set,s=[];a.forEach((e=>{const t=e.match(/curl\s+'([^']+)'/);t&&t[1]&&(c.has(t[1])||(c.add(t[1]),s.push(t[1])))}));let d="",u=1;if(s.forEach((t=>{const n=new RegExp(`curl\\s+'${t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}'[\\s\\S]+?(?=curl\\s+'|$)`,"g"),o=e.match(n);if(o&&o[0]){let e=o[0];e=e.replace(/-H\s+'range:\s+bytes=.*?'\s+\\\n/g,"");const t=String(u).padStart(2,"0");e=e.replace(/curl\s+'/,"curl '");const n=e.indexOf("' \\");-1!==n&&(e=e.substring(0,n+3)+`\n--location \\\n-o file-${t}.mp3 \\`+e.substring(n+3)),d+=e,u++}})),u>1){const e="01",n=String(u-1).padStart(2,"0");let r="";o&&(r=`# Create and enter directory for "${t}"\nmkdir -p "${o}"\ncd "${o}"\n\n`),d=r+d,d+=`\n\n# Concatenate all downloaded MP3 files\nmp3wrap output.mp3 file-{${e}..${n}}.mp3\n\n# Open the concatenated file in QuickTime Player\nopen -a "QuickTime Player" output_MP3WRAP.mp3\n`}l.value=d,l.select()}catch(e){l.value=`Error processing commands: ${e.message}`}}c.textContent="Close",c.style.cssText="background-color: #f44336;color: white;padding: 10px 15px;border: none;border-radius: 4px;cursor: pointer;font-size: 16px;align-self: center;",a.addEventListener("click",i),c.addEventListener("click",(()=>{document.body.removeChild(e)})),t.appendChild(n),t.appendChild(o),t.appendChild(r),t.appendChild(a),t.appendChild(l),t.appendChild(c),e.appendChild(t),document.body.appendChild(e),r.focus()})();

Usage

Step 1: Extract MP3 URLs

  1. Visit https://libbyapp.com/shelf/loans
  2. Click on the book you would like to download
  3. Right-click on the player page and choose the "Inspect" menu option
  4. Click on the "Network" tab
  5. Click on the funnel icon and enter status-code:206 in the filter text box
  6. Click on your "Libby Extract URLs" bookmarklet
    • This will begin playing and fast-forwarding the audiobook simultaneously
    • The browser will download all constituent MP3 files
    • To stop the process at any time, press the Escape key
  7. Once the full audiobook has played through, right-click on one of the filenames in the "Name" list on the bottom left
  8. Select "Copy > Copy all as cURL (bash)"

Step 2: Process the cURL Commands

  1. Open any web page (or a blank tab)
  2. Click on your "cURL Processor" bookmarklet
  3. Paste the list of cURL commands copied in Step 1 into the textarea
  4. Click the "Process" button
  5. Copy the processed commands from the result box
  6. Run the commands in your terminal to download and concatenate the MP3 files

How It Works

The bookmarklets:

  • Extract URLs by automatically playing through the audiobook
  • Process cURL commands to create organized download scripts
  • Create directories based on book titles
  • Remove duplicates and add proper filenames
  • Generate commands to concatenate files and open them in QuickTime Player
  • All processing happens locally in your browser

Privacy Note

All processing happens locally in your browser. No data is sent to any server.

Disclaimer

This tool is provided for personal use only. Please respect copyright laws and terms of service for the content you download.

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