Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

AppleScript to take screenshot of a specific area and save to desktop

Hello,


I need to have an Applescript that takes a screenshot (or invokes Mac OS X's screen picture taking) of a specific area of the screen (say from 911x173 to 1738x794) and then saves the result in .png on the desktop with date and time (much like a cmd-shift-4 would do).


Any help much appreciated.


Thanks in advance.

Peter 🙂


++++

CinemaDisplay 24"-OTHER, OS X Mavericks (10.9), 2.6 GHz Intel Core i7, 8 GB/750 GB

Posted on Dec 7, 2013 6:33 AM

Reply
Question marked as Best reply

Posted on Dec 7, 2013 11:06 AM

Hello


You may try something like the following script. I assumed (911, 173) and (1738, 794) are x, y-coordinates of top-left and bottom-right corners of target rectangle. It will yield a png file named "yyyy-mm-dd hh.mm.ss.png" on desktop.


set {l, t, r, b} to {911, 173, 1738, 794}
set {x, y, w, h} to {l, t, r - l, b - t}
screencapture(x, y, w, h)

on screencapture(x, y, w, h)
    (*
        number x, y, w, h: rectangle parameters
            (x, y) = x, y-coordinates of origin point
            (w, h) = width and height of rectangle
            
        * screen shot is saved as ~/Desktop/yyyy-mm-dd hh.mm.ss.png
    *)
    set args to ""
    repeat with a in {x, y, w, h}
        set args to args & space & ("" & a)'s quoted form
    end repeat
    considering numeric strings
        if (system info)'s system version < "10.9" then
            set ruby to "/usr/bin/ruby"
        else
            set ruby to "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby"
        end if
    end considering
    do shell script ruby & " <<'EOF' - " & args & "
require 'osx/cocoa'
include OSX
raise AugumentError, \"Usage: #{File.basename($0)} x, y, w, h\" unless ARGV.length == 4
x, y, w, h = ARGV.map {|a| a.to_f}
outfile = File.expand_path(%x[date +'%F %H.%M.%S.png'].chomp, '~/Desktop')
img = CGDisplayCreateImageForRect(CGMainDisplayID(), CGRectMake(x, y, w, h))
brep = NSBitmapImageRep.alloc.initWithCGImage(img)
data = brep.objc_send(
    :representationUsingType, NSPNGFileType,
    :properties, {})
data.objc_send(
    :writeToFile, outfile,
    :atomically, false)
EOF"
end screencapture


Hope this may help,

H

23 replies
Question marked as Best reply

Dec 7, 2013 11:06 AM in response to Peter Deli

Hello


You may try something like the following script. I assumed (911, 173) and (1738, 794) are x, y-coordinates of top-left and bottom-right corners of target rectangle. It will yield a png file named "yyyy-mm-dd hh.mm.ss.png" on desktop.


set {l, t, r, b} to {911, 173, 1738, 794}
set {x, y, w, h} to {l, t, r - l, b - t}
screencapture(x, y, w, h)

on screencapture(x, y, w, h)
    (*
        number x, y, w, h: rectangle parameters
            (x, y) = x, y-coordinates of origin point
            (w, h) = width and height of rectangle
            
        * screen shot is saved as ~/Desktop/yyyy-mm-dd hh.mm.ss.png
    *)
    set args to ""
    repeat with a in {x, y, w, h}
        set args to args & space & ("" & a)'s quoted form
    end repeat
    considering numeric strings
        if (system info)'s system version < "10.9" then
            set ruby to "/usr/bin/ruby"
        else
            set ruby to "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby"
        end if
    end considering
    do shell script ruby & " <<'EOF' - " & args & "
require 'osx/cocoa'
include OSX
raise AugumentError, \"Usage: #{File.basename($0)} x, y, w, h\" unless ARGV.length == 4
x, y, w, h = ARGV.map {|a| a.to_f}
outfile = File.expand_path(%x[date +'%F %H.%M.%S.png'].chomp, '~/Desktop')
img = CGDisplayCreateImageForRect(CGMainDisplayID(), CGRectMake(x, y, w, h))
brep = NSBitmapImageRep.alloc.initWithCGImage(img)
data = brep.objc_send(
    :representationUsingType, NSPNGFileType,
    :properties, {})
data.objc_send(
    :writeToFile, outfile,
    :atomically, false)
EOF"
end screencapture


Hope this may help,

H

Dec 9, 2013 10:46 AM in response to Hiroto

Hiroto,


Great script. I'm trying to adapt it to bash, but I'm getting an error, could you tell me where I'm going wrong?


#!/bin/bash

# screenshot area
x=0
y=0
w=$((1365-$x))
h=$((767-$y))

OSXver=$(sw_vers -productVersion)
if [ $OSXver > "10.9" -o $OSXver = "10.9" ] ; then 
          ruby="/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby"
else
          ruby="/usr/bin/ruby"
fi
$ruby <<END
"$x" "$y" "$w" "$h"
require 'osx/cocoa'
include OSX
raise AugumentError, "Usage: #{File.basename($0)} x, y, w, h" unless ARGV.length == 4 x, y, w, h = ARGV.map {|a| a.to_f}
outfile = File.expand_path(%x[date +'%F %H.%M.%S.png'].chomp, '~/Desktop')
img = CGDisplayCreateImageForRect(CGMainDisplayID(), CGRectMake(x, y, w, h))
brep = NSBitmapImageRep.alloc.initWithCGImage(img)
data = brep.objc_send(
    :representationUsingType, NSPNGFileType,
    :properties, {})
data.objc_send(
    :writeToFile, outfile,
    :atomically, false)
END

Dec 9, 2013 12:28 PM in response to Tony T1

Hello


This seems to work.


#!/bin/bash

# screenshot area
x=0
y=0
w=$((1365-$x))
h=$((767-$y))

OSXver=$(sw_vers -productVersion)
if [[ $OSXver < "10.9" ]]; then 
    ruby="/usr/bin/ruby"
else
    ruby="/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby"
fi

$ruby <<'END' - "$x" "$y" "$w" "$h"
require 'osx/cocoa'
include OSX
raise ArgumentError, "Usage: #{File.basename($0)} x, y, w, h" unless ARGV.length == 4
x, y, w, h = ARGV.map {|a| a.to_f}
outfile = File.expand_path(%x[date +'%F %H.%M.%S.png'].chomp, '~/Desktop')
img = CGDisplayCreateImageForRect(CGMainDisplayID(), CGRectMake(x, y, w, h))
brep = NSBitmapImageRep.alloc.initWithCGImage(img)
data = brep.objc_send(
    :representationUsingType, NSPNGFileType,
    :properties, {})
data.objc_send(
    :writeToFile, outfile,
    :atomically, false)
END


The point is to quote END and put - before arguments to tell ruby the script is given via STDIN:


$ruby <<'END' - "$x" "$y" "$w" "$h"


I changed the version check code a bit, for the original one did not work correctly.

AND fixed my original typo as well : AugumentError => ArgumentError.. Haha.


Kind regards,

H

Dec 9, 2013 12:47 PM in response to Peter Deli

Hello Peter,


Thanks to Tony T1, a typo was found in error reporting statement: AugumentError should have been ArgumentError.

This won't surface in normal case but here's the fixed code in case. 😉



set {l, t, r, b} to {911, 173, 1738, 794}
set {x, y, w, h} to {l, t, r - l, b - t}
screencapture(x, y, w, h)

on screencapture(x, y, w, h)
    (*
        number x, y, w, h: rectangle parameters
            (x, y) = x, y-coordinates of origin point
            (w, h) = width and height of rectangle

        * screen shot is saved as ~/Desktop/yyyy-mm-dd hh.mm.ss.png
    *)
    set args to ""
    repeat with a in {x, y, w, h}
        set args to args & space & ("" & a)'s quoted form
    end repeat
    considering numeric strings
        if (system info)'s system version < "10.9" then
            set ruby to "/usr/bin/ruby"
        else
            set ruby to "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby"
        end if
    end considering
    do shell script ruby & " <<'EOF' - " & args & "
require 'osx/cocoa'
include OSX
raise ArgumentError, \"Usage: #{File.basename($0)} x, y, w, h\" unless ARGV.length == 4
x, y, w, h = ARGV.map {|a| a.to_f}
outfile = File.expand_path(%x[date +'%F %H.%M.%S.png'].chomp, '~/Desktop')
img = CGDisplayCreateImageForRect(CGMainDisplayID(), CGRectMake(x, y, w, h))
brep = NSBitmapImageRep.alloc.initWithCGImage(img)
data = brep.objc_send(
    :representationUsingType, NSPNGFileType,
    :properties, {})
data.objc_send(
    :writeToFile, outfile,
    :atomically, false)
EOF"
end screencapture


All the best,

Hiroto

Jul 11, 2014 11:19 AM in response to Hiroto

Hiroto-san! Konnichiwa doitsukara! Boku wa Archy desu. Yoroshikuonegaishimasu!


Thank you for sharing this elegant solution!


However, I am getting an error message:


/System/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/oc_import .rb:192:in `const_missing': uninitialized constant EOF (NameError)

from -:14


I tried running the script as an Applescript, and I also tried to run the version you created for the Terminal - both ways give the message. (The only change I made to the script are the x,y,w,h variables)


My operating system is OSX 10.6.3


Here is a screen image showing the error:


User uploaded file

My Applescript skills are still very weak. Thank you in advance for any assistance or suggestions you can share.


Hontoni arigatougozaimasu!


douzo ogenkide,

Archy

Jul 11, 2014 4:46 PM in response to Archydolder

Archy-san Konnichiwa,


I think this is another problem of new fora software, that is the code copied from the page has leading spaces in front of every line which do not exist in the original. These unwanted indents are observed in copied code when I use Firefox (24.6.0esr) with JavaScript enabled to browse this site, whilst they are not present when I disable JavaScript or I use Safari (5.1.10). I'm using OSX 10.6.8.


Anyway, you need to remove all those unwanted spaces in front of each line of code so that the first line indent becomes none. (The error you're seeing is due to the last "EOF" not being at the beginning of line.)


Oyakuni tatereba koueidesu.

I'm honoured if it serves you.


Hiroto 🙂

Jul 12, 2014 10:16 AM in response to Hiroto

Hiroto-sensei! Konnichiwa! Sugoi!


Removing the leading blank spaces solved the error problem! I copied the script from a FireFox v22.0 window with JS running. The unwanted spaces probably also appear with other browsers / versions / configurations. I have learned an important lesson!


Your script is truly a beautiful solution! Thank you again for sharing your work and your knowledge!


Arigatougozaimashita!

Archy

Nov 8, 2016 2:03 PM in response to Archydolder

Dear Hiroto, Archydolder and the others,


At first thank you for this script, it would solve my problem as well.

I need some help.

Unfortunatly I had almost the same error message as Archydolder had. This is my error:


error "sh: /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby: No such file or directory" number 127


I tried the following things:

- Copied the script from safari and firefox.

- In both cases I tried with enabled/disabled JavaScript.

- Tried to find all the blank spaces after copying the script in AppleScript and delete them.


What do I do wrong? I had this error message in every cases I tried.


I have a 10.0.1 Safari, a 49.0.2 Firefox on my Mac, and run Mac OS X 10.10.5


Please help me.


Thank you in advance,

fabee

Nov 8, 2016 5:56 PM in response to fabee.zz

It is not your fault. Apple broke the Ruby scripting bridge with Mavericks (10.9) and never fixed it afterward. Thus, Ruby applications attempting to use Cocoa frameworks fail.


For Mavericks and Yosemite, there is an open source RubyCocoa v1.2.0 binary distribution that effectively patches the scripting bridge, allowing Hiroto's application to work again. It won't install on El Capitan, and must be compiled from source to install and work there. It won't even compile for macOS Sierra without some modifications to the source, and it is no longer supported as far as I can tell.


Hiroto may come along and rewrite this solution in Python Objective-C.


Here is a pure AppleScript solution that may prove useful for you, and is not based on Hiroto's work.


-- capture.applescript

--

-- enter screen coordinates for capture, and silently produces png with name

-- "Screen Shot yyyy-dd-mm at hh.mm.ss AM/PM".png

-- Version 1

-- VikingOSX, Nov. 8, 2016, Apple Support Communities


use scripting additions


set outdest to POSIX path of (path to desktop as text)

set msg to "Enter your start, and end coordinates as:" & return & ¬

"start-x,start-y,end-x,end-y" & return & "(e.g. 257,222,123,94)"


-- get the display size

tell application "Finder"

set {missing value, missing value, swidth, sheight} to get bounds of window of desktop

end tell


set screen_coord to text returned of (display dialogmsgdefault answer "")

set {TID, AppleScript'stext item delimiters} to {AppleScript'stext item delimiters, ","}

set mycoords to text items of screen_coord

set AppleScript'stext item delimiters to TID


-- validate that provided coordinates are within display boundaries

considering numeric strings

repeat with apoint in mycoords

if apoint > swidth or apoint > sheight then

display alert "Coordinate choices are outside screen size: w: " & swidth & " h: " & sheight

return

end if

end repeat

end considering


set dateStr to do shell script "date \"+%F at %H.%M.%S %p\""

set outfile to (outdest & "Screen Shot " & dateStr & ".png")'s quoted form


-- Add the -P option if you want the screen shot opened in Preview too

do shell script "/usr/sbin/screencapture -R " & screen_coord & space & outfile

return

AppleScript to take screenshot of a specific area and save to desktop

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.