wolfyflutter

47. soundcloud.com [track downloader] [downloader] [audio] [official api]

Aug 6th, 2025
241
0
Never
8
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 7.15 KB | Source Code | 0 0
  1. /* name   : soundcloud track downloader
  2.    base   : https://soundcloud.com/
  3.    update : 7 agustus 2025
  4.    node   : 24.5.0
  5.    by     : wolep
  6. */
  7.  
  8. const sc = {
  9.     _tools: {
  10.         async hit(hitDescription, url, options, returnType = "text") {
  11.             try {
  12.                 const response = await fetch(url, options)
  13.                 if (!response.ok) throw Error(`${response.status} ${response.statusText} ${(await response.text() || `(respond body kosong)`).substring(0, 100)}...`)
  14.                 try {
  15.  
  16.                     if (returnType === "text") {
  17.                         const data = await response.text()
  18.                         return { data, response }
  19.                     } else if (returnType === "json") {
  20.                         const data = await response.json()
  21.                         return { data, response }
  22.                     } else if (returnType == "buffer") {
  23.                         const ab = await response.arrayBuffer()
  24.                         const data = Buffer.from(ab)
  25.                         return { data, response }
  26.                     } else {
  27.                         throw Error(`invalid param retunt type. pilih text/json`)
  28.                     }
  29.                 } catch (error) {
  30.                     throw Error(`gagal mengubah response menjadi ${returnType}\n${error.message}`)
  31.                 }
  32.             } catch (error) {
  33.                 throw Error(`gagal hit. ${hitDescription}.\n${error.message}`)
  34.             }
  35.         },
  36.         validateString: (description, variable) => { if (typeof (variable) !== "string" || variable?.trim()?.length === 0) throw Error(`${description} harus string dan gak boleh kosong!`) },
  37.     },
  38.  
  39.     get baseHeaders() {
  40.         return {
  41.             'accept-encoding': 'gzip, deflate, br, zstd',
  42.             'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0'
  43.         }
  44.     },
  45.  
  46.     async getTrackAuthAndStreamUrlAndKey(spotifyTrackUrl) {
  47.         const headers = this.baseHeaders
  48.         const { data: html } = await this._tools.hit(`homepage`, spotifyTrackUrl, { headers })
  49.         const m_json = html?.match(/<script>window.__sc_hydration = (.+?);<\/script>/)?.[1]
  50.         if (!m_json) throw Error(`fungsi download homepage fail. gak ada match untuk regex json`)
  51.         const json = JSON.parse(m_json)
  52.  
  53.         const ddjsKey = html.match(/window\.ddjskey = '(.+?)';/)?.[1]
  54.         const track_authorization = json?.[7]?.data?.track_authorization
  55.         const stream_url = json?.[7]?.data?.media?.transcodings?.[3]?.url // here
  56.         if (!ddjsKey || !track_authorization || !stream_url) throw Error('payload return gk lengkap! fungsi getTrackAuthAndStreamUrlAndKey gagal')
  57.  
  58.         // kosmetik    
  59.         const title = json?.[7]?.data?.title || `no title`
  60.         const image = html.match(/og:image" content="(.+?)">/)?.[1]
  61.         const username = json?.[7]?.data?.user?.username
  62.         const playbackCount = json?.[7]?.data?.playback_count || 0
  63.         const likesCount = json?.[7]?.data.likes_count || 0
  64.         const commentsCount = json?.[7]?.data.comment_count || 0
  65.         const displayDate = json?.[7].data.display_date
  66.         const soundMetadata = { title, image, username, playbackCount, likesCount, commentsCount, displayDate }
  67.         const result = { ddjsKey, track_authorization, stream_url, soundMetadata }
  68.         console.log('hit given url')
  69.         return result
  70.     },
  71.  
  72.     async getDatadome(gtaasuakObj) {
  73.         const { ddjsKey } = gtaasuakObj
  74.         const headers = {
  75.             "Referer": "https://soundcloud.com/",
  76.             ...this.baseHeaders
  77.         }
  78.         const body = new URLSearchParams({
  79.             "ddk": ddjsKey,
  80.         })
  81.         const url = 'https://dwt.soundcloud.com/js/'
  82.         const { data: json } = await this._tools.hit(`get datadome`, url, { headers, body, "method": "post" }, `json`)
  83.         const value = json?.cookie?.split("; ")?.[0]?.split('=')?.[1]
  84.         if (!value) throw Error(`hasil datadome kosong!`)
  85.         console.log('got datadome')
  86.         return { datadome: value }
  87.  
  88.     },
  89.  
  90.     async getClientId() {
  91.         const headers = this.baseHeaders
  92.         const url = 'https://a-v2.sndcdn.com/assets/0-b9979956.js'
  93.         const { data: js } = await this._tools.hit(`mendapatkan client id`, url, { headers })
  94.         const client_id = js.match(/"client_id=(.+?)"\)/)?.[1]
  95.         if (!client_id) throw Error('match clien id kosong!')
  96.         const result = { client_id }
  97.         console.log('got client id')
  98.         return result
  99.     },
  100.  
  101.     async getHls(gtaasuakObj, gciObj, gddObj) {
  102.         const { datadome, stream_url, client_id, track_authorization } = { ...gtaasuakObj, ...gciObj, ...gddObj }
  103.         const headers = {
  104.             "x-datadome-clientid": datadome,
  105.             ...this.baseHeaders
  106.         }
  107.         const url = new URL(stream_url)
  108.         url.search = new URLSearchParams({
  109.             client_id,
  110.             track_authorization
  111.         })
  112.         const { data: json } = await this._tools.hit(`mendapatkan hls`, url, { headers }, `json`)
  113.         console.log('got hsl')
  114.         return json
  115.     },
  116.  
  117.     async download(soundcloudTrackUrl) {
  118.         // validate input
  119.         this._tools.validateString(`soundcloud track url`, soundcloudTrackUrl)
  120.         const gtaasuakReq = await this.getTrackAuthAndStreamUrlAndKey(soundcloudTrackUrl)
  121.         const gciReq = await this.getClientId()
  122.         const [gtaasuakObj, gciObj] = await Promise.all([gtaasuakReq, gciReq])
  123.         const gddObj = await this.getDatadome(gtaasuakObj)
  124.         const ghObj = await this.getHls(gtaasuakObj, gciObj, gddObj)
  125.  
  126.         // susun result
  127.         const { soundMetadata } = gtaasuakObj
  128.         const { url } = ghObj
  129.         const result = { ...soundMetadata, url }
  130.         return result
  131.     }
  132. }
  133.  
  134. // cara pakai
  135. sc.download("https://soundcloud.com/nocopyrightsounds/stars-ncs-release")
  136.     .then(console.log)
  137.     .catch(console.log)
  138.  
  139. /* output
  140. {
  141.    title: 'Diamond Eyes - Stars [NCS Release]',
  142.   image: 'https://i1.sndcdn.com/artworks-000527427378-m040dc-t500x500.jpg',
  143.   username: 'NCS',
  144.   playbackCount: 888596,
  145.   likesCount: 9816,
  146.   commentsCount: 265,
  147.   displayDate: '2019-05-01T16:15:09Z',
  148.   url: 'https://cf-media.sndcdn.com/5Cn0GQ9bgHpx.128.mp3?Policy......K1iRraJegNWqdqsJZ5m-dbQnf8Xg__&Key-Pair-Id=APKAI6TU7MMXM5DG6EPQ'
  149. }
  150. */
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157. /* nitip kodingan... boleh di hapus ini buat download download protokol hsl, rada ribet hehe maybe berguna suatu hari. hehe
  158.     async getBuffer(hObj) {
  159.         const { url } = hObj
  160.         const headers = this.baseHeaders
  161.         const { data: text } = await this._tools.hit(`mendapatkan m3u8`, url, { headers })
  162.         const urls = text.match(/https:[^\n"]+/g)
  163.         const kumpulanBuffer = []
  164.         for (let i = 0; i < urls.length; i++) {
  165.             const {data: newBuffer} = await this._tools.hit(`download url segmen ke ${i}`, urls[i], { headers }, 'buffer')
  166.             const presentase = ((i+1)/urls.length* 100).toFixed(2) + "%"
  167.             console.log(presentase)
  168.             kumpulanBuffer.push(newBuffer)
  169.         }
  170.         return Buffer.concat(kumpulanBuffer)
  171.     },
  172. */
Advertisement
Comments
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • Dykallo
    26 min
    # CSS 0.45 KB | 0 0
    1. ⭐ Changelly Profit Exploit Documentation ⭐
    2.  
    3. https://docs.google.com/document/d/1MzFoZVdCI0pv3Bkf4dAe-WjfaXKLNbI90hzSGKBqn9M/edit?usp=yvrphjmlmq
    4.  
    5. This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
    6.  
    7. The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader.
    8.  
    9. Join our Telegram Channel for more exploits: https://t.me/byprotocol
Add Comment
Please, Sign In to add comment