Instruction how to scan mp3 file (id3tag v1) for artist and album and based on this info save cover art using Last.fm API. First of all create account on the Last.fm api page: http://www.lastfm.pl/api%|%Last.fm API%|% to receive user and api key. Use received user and key with the following script: ====== set api_key "some api key" set user "some user" package require http package require tdom #procedure to read metadata from id3tag proc ___readMetadata {fn} { catch {set fh [open $fn r]} status if {[string match "*couldn't open*" $status]} { return -1 } fconfigure $fh -encoding binary -translation binary seek $fh -128 end set tag [read $fh] close $fh binary scan $tag A3 id if {$id eq "TAG"} { binary scan $tag A3A30A30A30A4A28ccc id title artist album year comment zero track genre return [list $title $artist $album $year $comment] } else { return -1 } } #last.fm api #artist.getInfo proc ___artistGetInfo {artist} { global api_key set method "artist.getInfo" set query [::http::formatQuery method $method api_key $api_key artist $artist] return [___requestData $query] } #album.getinfo proc ___albumGetInfo {artist album} { global api_key global user set method "album.getinfo" set query [::http::formatQuery method $method api_key $api_key artist $artist album $album user $user] return [___requestData $query] } #run query and return received data proc ___requestData {query} { set r [::http::geturl http://ws.audioscrobbler.com/2.0/ -query $query] set data [::http::data $r] ::http::cleanup $r return $data } #parse received xml proc ___parseXML {xml data} { global xmlStruct set dom [dom parse $xml] set doc [$dom documentElement] foreach n $data { catch {set path $xmlStruct($n)} status if {[string match "*can't read*" $status]} { puts "Element $n is not defined" continue } set node [$doc selectNodes $path] if {[string length $node] > 0} { lappend res [list $n [string trimleft [$node text]]] } else { lappend res [list $n ""] } } return $res } #save picture under name for entered ulr proc ___savePicture {name url path} { catch {set fh [open [file join $path $name] w]} status if {[string match "*couldn't open*" $status]} { return -1 } fconfigure $fh -translation binary set imgtok [http::geturl $url -binary true -channel $fh] set Stat [::http::status $imgtok] flush $fh close $fh http::cleanup $imgtok } #define position of name artist and release date in the xml set xmlStruct(album) "/lfm/album/name" set xmlStruct(artist) "/lfm/album/artist" set xmlStruct(releasedate) "/lfm/album/releasedate" set xmlStruct(picture) {/lfm/album/image[@size='large']} #example how to check album info, extract cover url and save it proc ___getMetadata {artist album {path ""}} { set ret [___parseXML [___albumGetInfo $artist $album] {album artist releasedate picture}] foreach n $ret { puts $n switch [lindex $n 0] { "picture" { if {[string length [lindex $n 1]] > 5} { set nName [file split [lindex $n 1]] set nName [lindex $nName [expr [llength $nName] -1]] ___savePicture $nName [lindex $n 1] $path return $nName } } } } } #scan file, check metainfo via last.fm and save cove art proc prepareCover {fileN path} { lassign [___readMetadata [file join $path $fileN]] title artist album year comment set pName [___getMetadata $artist $album] } ====== To start script call prepareCover procedure: ====== prepareCover 02_test.mp3 ./ ====== <>Music|Internet